Win9x 每個進程擁有獨立 4GB 虛擬位址空間,無法直接讀寫彼此記憶體。系統提供兩種官方跨進程資料交換機制。
適用場景:小量資料 (< 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_COPYDATA | Memory Mapped File |
|---|---|---|
| 資料量 | 建議 < 64KB | 可達數百 MB (受分頁檔限制) |
| 同步性 | 發送端阻塞直到接收端處理完 | 非同步,需額外同步物件 |
| 生命週期 | 隨訊息單次傳遞 | 持久,直到所有進程關閉 Handle |
| 跨網路 | 不支援 | 不支援 (需命名管道/通訊端) |
| 實作複雜度 | 低 | 中 (需同步設計) |