首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Win9x 進程間資料傳遞:WM_COPYDATA 與記憶體映射檔 兩大機制完整對比與代碼範例

     編輯:Delphi

背景

Win9x 每個進程擁有獨立 4GB 虛擬位址空間,無法直接讀寫彼此記憶體。系統提供兩種官方跨進程資料交換機制。

機制一:WM_COPYDATA 訊息

適用場景:小量資料 (< 64KB)、單向/請求-回應、簡單同步。
核心結構:

TCopyDataStruct = packed record
  dwData: DWORD;   // 自定義標識
  cbData: DWORD;   // 資料長度 (位元組)
  lpData: Pointer; // 資料緩衝區指標 (發送端有效)
end;

發送端

procedure TForm1.Edit1Change(Sender: TObject);
var
  CDS: TCopyDataStruct;
  Buf: PAnsiChar;
  Target: HWND;
begin
  CDS.dwData := 0;
  CDS.cbData := Length(Edit1.Text) + 1; // 含結束符
  GetMem(Buf, CDS.cbData);
  StrCopy(Buf, PAnsiChar(AnsiString(Edit1.Text)));
  CDS.lpData := Buf;

  Target := FindWindow('TForm1', 'GetCopyData'); // 目標視窗類別/標題
  if Target = 0 then
  begin
    ShowMessage('找不到目標視窗');
    FreeMem(Buf);
    Exit;
  end;

  SendMessage(Target, WM_COPYDATA, Handle, LPARAM(@CDS));
  FreeMem(Buf); // SendMessage 同步返回後即可釋放
end;

接收端

type
  TForm1 = class(TForm)
  private
    procedure WMCopyData(var Msg: TWMCopyData); message WM_COPYDATA;
  end;

procedure TForm1.WMCopyData(var Msg: TWMCopyData);
begin
  with Msg.CopyDataStruct^ do
    Edit1.Text := string(AnsiString(PAnsiChar(lpData))); // 依實際編碼轉換
  Msg.Result := 1; // 表示已處理
end;

機制二:記憶體映射檔

適用場景:大量資料、高頻共享、雙向、持久化共享緩衝區。
核心 API:`CreateFileMapping` / `OpenFileMapping` / `MapViewOfFile` / `UnmapViewOfFile` / `CloseHandle`。
同步:需自行加互斥體 (`CreateMutex`)、事件 (`CreateEvent`) 或關鍵區域。

寫入端

procedure TForm1.FormCreate(Sender: TObject);
begin
  hMap := CreateFileMapping($FFFFFFFF, nil, PAGE_READWRITE, 0, 1000, 'MySharedMem');
  if hMap = 0 then RaiseLastOSError;
  pView := MapViewOfFile(hMap, FILE_MAP_WRITE, 0, 0, 0);
  if pView = nil then RaiseLastOSError;
end;

procedure TForm1.Edit1Change(Sender: TObject);
var
  S: AnsiString;
begin
  S := AnsiString(Edit1.Text);
  Move(PAnsiChar(S)^, pView^, Length(S) + 1); // 複製含結束符
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  if pView <> nil then UnmapViewOfFile(pView);
  if hMap <> 0 then CloseHandle(hMap);
end;

讀取端

procedure TForm1.FormCreate(Sender: TObject);
begin
  hMap := OpenFileMapping(FILE_MAP_READ, False, 'MySharedMem');
  if hMap = 0 then RaiseLastOSError;
  pView := MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
  if pView = nil then RaiseLastOSError;
  Timer1.Enabled := True;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  Edit1.Text := string(AnsiString(PAnsiChar(pView))); // 週期性輪詢
end;

兩機制對比表

維度WM_COPYDATAMemory Mapped File
資料量建議 < 64KB可達數百 MB (受分頁檔限制)
同步性發送端阻塞直到接收端處理完非同步,需額外同步物件
生命週期隨訊息單次傳遞持久,直到所有進程關閉 Handle
跨網路不支援不支援 (需命名管道/通訊端)
實作複雜度低中 (需同步設計)

現代 Windows (NT 系) 補充

  • NT 核心下 `WM_COPYDATA` 同樣支援跨 Session (需 `ChangeWindowMessageFilterEx`)。
  • 大數據高效能首選 **I/O Completion Port + 共享記憶體** 或 **命名管道**。
  • Managed 代碼 (C#/VB.NET) 可用 `MemoryMappedFile` 類別簡化操作。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved