使用WM_COPYDATA跨進程發送數據


進程之間通訊的幾種方法:

在Windows程序中,各個進程之間常常需要交換數據,進行數據通訊。常用的方法有

使用內存映射文件
通過共享內存DLL共享內存
使用SendMessage向另一進程發送WM_COPYDATA消息

比起前兩種的復雜實現來,WM_COPYDATA消息無疑是一種經濟實惠的一中方法。WM_COPYDATA消息的主要目的是允許在進程間傳遞只讀數據。Windows在通過WM_COPYDATA消息傳遞期間,不提供繼承同步方式。SDK文檔推薦用戶使用SendMessage函數,接受方在數據拷貝完成前不返回,這樣發送方就不可能刪除和修改數據。注意,接受方在DefWndProc事件中,來處理這條消息。由於中文編碼是兩個字節,所以傳遞中文時候字節長度要搞清楚。

用WM_COPYDATA的前提:
1,知道接收消息進程的句柄。
2,接收消息進程重載了WM_COPYDATA消息映射,能對其做出反應(否則不是發送端自作多情了?)

前幾天寫程序用到WM_COPYDATA進行進程間通信,但是接收方怎么也收不到消息。調試發現找到的窗口句柄是沒有問題的,查看MSDN也沒有什么提示,百思不得其解。后來看了一些示例代碼,發現不同之處是我的SendMessage調用中wParam和lParam參數都是0,因為我只是需要通過WM_COPYDATA消息通知一下接收程序即可,不用傳遞任何數據。試着將這兩個參數改為非空,接收方就可以收到消息了。總結結論為:wParam參數是否為0沒有影響,但是lParam參數必須為非空,即必須指向一個有效的COPYDATASTRUCT結構體。原因是什么呢?查了一些資料發現,SendMessage(WM_COPYDATA)底層是通過文件映射(File Mapping)完成的,大概流程是發送方線程根據COPYDATASTRUCT結構體中的傳遞數據信息,在共享內存中進行數據復制,接收方線程則會到共享內存中讀取數據進行處理。因此如果指向COPYDATASTRUCT結構的指針為空的話,流程是無法進行的,所以接收方也理所當然收不到消息。

 

procedure TForm1.Button2Click(Sender: TObject);
var
  Receiver: THandle;
  buffer: array[0..1023] of char;
  Data: TCopyDataStruct;
begin
  Receiver := FindWindow('TReceiverForm', nil);
  if Receiver > 0 then
  begin
    StrPLCopy(@buffer, Edit1.Text, 1024); // Assumes message in Editbox
    Data.dwData := 0;
    Data.cbData := 1024;
    Data.lpData := @buffer;
    SendMessage(Receiver, WM_COPYDATA, 0, LongInt(@Data));
  end;
end;

type
  TForm1 = class(TForm)
    { ... }
  private
    { ... }
  protected
    procedure WmCopyData(var Msg: TMessage); message WM_COPYDATA;
  public
    { ... }
  end;

procedure TForm1.WmCopyData(var Msg: TMessage);
begin
  ShowMessage(
    'This message sent:' + #13 +
    string(PChar(PCopyDataStruct(Msg.LParam)^.lpData))
  );
end;

參考:http://www.xuebuyuan.com/976757.html

http://blog.csdn.net/iseekcode/article/details/4821082


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM