1. 程式人生 > 其它 >Windows程序通訊 -- WM_COPYDATA 訊息

Windows程序通訊 -- WM_COPYDATA 訊息

來自:https://blog.csdn.net/u012104827/article/details/102914600

關於 WM_COPYDATA 訊息說明:https://docs.microsoft.com/zh-cn/windows/win32/dataxchg/wm-copydata

COPYDATASTRUCT有三個成員變數,如下所示:

typedef struct tagCOPYDATASTRUCT {
  ULONG_PTR dwData;
  DWORD     cbData;
  PVOID     lpData;
} COPYDATASTRUCT, *PCOPYDATASTRUCT;

注意:


1、dwData為自定義資料,按照自己習慣設定就好,不影響物件的傳輸;


2、cbData,MSDN解釋為:The size, in bytes, of the data pointed to by the lpData member.即lpData指向的資料的長度,要是這個變數的值設定錯誤,就會導致WM_COPYDATA傳輸資料失敗;


3、lpData,傳輸的資料。使用簡單的資料最好,例如char陣列。本人在程式中使用了string物件,發現在子程序不能接收到正常的資料,使用char陣列卻很正常。有可能跟string物件不能跨程序訪問有關,讀者如果知道原因的話請在評論區告訴我,謝謝;


4、使用WM_COPYDATA時要用SendMessage而不能使用PostMessage

,因為SendMessage是阻塞的,會等待訊息響應窗體處理訊息完畢後再返回;而PostMessage是非同步的,這樣就可能會導致當訊息響應窗體接收到WM_COPYDATA的時候,COPYDATASTRUCT物件已經被析構了,導致訪問資料發生異常;


5、由於使用SendMessage,所以不應該在WM_COPYDATA中處理資料,可以在訊息響應窗體的WM_COPYDATA中先把COPYDATASTRUCT物件中的資料複製出來,通過自定義訊息傳送到訊息響應窗體,然後立即返回,來減少父程序的阻塞時間。這樣就把處理資料的程式碼放在自定義訊息處了。

在另一篇文章中 https://blog.csdn.net/syb1295306116/article/details/104155986,有這麼一段:

這裡注意要分配全域性記憶體,否則另一程序接受訊息時,訊息被釋放,接受的是亂碼,無法解析。

const UINT messageID = RegisterWindowMessage("SingletonApplication");
 
char szTemp[1024] = { 0 };
sprintf(szTemp, "LayeredWindow_%d", iWndID);//視窗名
HWND hTemp = ::FindWindow(NULL, szTemp);//視窗控制代碼
BYTE* pGlobal = (BYTE*)::GlobalAlloc(GMEM_FIXED, str.length());//全域性記憶體
if (!pGlobal)
{
    return;
}
else
{
    ZeroMemory(pGlobal, str.length());
    memcpy(pGlobal, str.c_str(), str.length());
}
COPYDATASTRUCT copyData = {0};
copyData.dwData = messageID;
copyData.cbData = (DWORD)(str.length()+1);
copyData.lpData = pGlobal;
SendMessage(hTemp, WM_COPYDATA, 0, (LPARAM)&copyData);
::GlobalFree((HGLOBAL)pGlobal);//釋放全域性記憶體

不過,我測試的時候,使用 malloc() 沒使用GlobalAlloc() ,倒也沒問題,不知何故?