完成進程間通信最簡單的方式就是發送WM_COPYDATA消息。
(1)發送WM_COPYDATA消息
SendMessage(接收窗口句柄, WM_COPYDATA, (WPARAM)發送窗口句柄, (LPARAM)©Data);
其中的copyData是要發送的數據,類型為COPYDATASTRUCT結構體:
typedef struct tagCOPYDATASTRUCT
{
DWORD dwData;
DWORD cbData;
PVOID lpData;
} COPYDATASTRUCT;
dwData : Specifies up to 32 bits of data to be passed to the receiving application.
cbData : Specifies the size, in bytes, of the data pointed to by the lpData member.
lpData : Long pointer to data to be passed to the receiving application. This member can be NULL.
該消息只能由SendMessage()發送,而不能使用PostMessage()。因為系統必須管理用以傳遞數據的緩沖區的生命期,如果使用了PostMessage(),數據緩沖區會在接收方(線程)有機會處理該數據之前,就被系統清除和回收。
如果傳入的接收窗口句柄無效或者當接收方進程意外終止時,SendMessage()會立即返回,發送方不會陷入一個無窮等待的狀態中。
此外還需注意:
The data being passed must not contain pointers or other references to objects not accessible to the application receiving the data.(所發送的數據不能包含數據接收方無法訪問的指針或對象引用)
While this message is being sent, the referenced data must not be changed by another thread of the sending process.(消息發送后,要保證lpData所引用數據不能被其它線程修改(直到SendMessage函數返回))
示例代碼片段(MFC):
HWND receiveWindow = ::FindWindow(NULL, "CopyDataReceiver"); if (receiveWindow == NULL) return; CString sendData; GetDlgItemText(IDC_EDIT_SEND, sendData); COPYDATASTRUCT copyData = { 0 }; copyData.lpData = sendData.GetBuffer(); copyData.cbData = sendData.GetLength(); ::SendMessage(receiveWindow, WM_COPYDATA, (WPARAM)GetSafeHwnd(), (LPARAM)©Data); sendData.ReleaseBuffer();
(2)接收WM_COPYDATA消息:
WM_COPYDATA
wParam = (WPARAM)(HWND) hwnd;
lParam = (LPARAM)(PCOPYDATASTRUCT) pcds;
hwnd: Handle to the window passing the data. (數據發送方的句柄,接收方可以通過此句柄向發送方反饋數據)
pcds: Pointer to a COPYDATASTRUCT structure that contains the data to be passed.
Return Values
If the receiving application processes this message, it should return TRUE; otherwise, it should return FALSE.
lParam包含了接收到的數據,在處理之前需要將類型轉換為COPYDATASTRUCT結構體。接收方應認為這些數據是只讀的,並且只在處理該消息的過程中有效。如果想修改這些數據,應該把它們復制到本地buffer。(The receiving application should consider the data read-only. The pcds parameter is valid only during the processing of the message. The receiving application should not free the memory referenced by pcds. If the receiving application must access the data after SendMessage returns, it must copy the data into a local buffer. )
由於發送方在接收方處理WM_COPYDATA消息完畢前都是處於等待(SendMessage阻塞)中,所以接收方應當盡快處理WM_COPYDATA消息。
示例代碼片段(MFC):
BOOL CCopyDataReceiverDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct) { if (pCopyDataStruct->cbData > 0) { char recvData[256] = {0} ; strncpy(recvData, (char *)pCopyDataStruct->lpData, pCopyDataStruct->cbData); SetDlgItemText(IDC_EDIT_RECEIVE, (char *)recvData); Feedback(pWnd); } return CDialog::OnCopyData(pWnd, pCopyDataStruct); }
參考資料:
[1] msdn
[2] http://blog.csdn.net/morewindows/article/details/6804157