WM_COPYDATA 进程间传递数据(以字符串为例)
Win32下很多时候,不同的进程之间需要通信,message是最常用的一种。可以通过SendMessage来向某个进程发送消息,前提是需要获取此进程的handle。
Syntax LRESULT SendMessage( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ); Parameters hWnd [in] Handle to the window whose window procedure will receive the message. If this parameter is HWND_BROADCAST, the message is sent to all top-level windows in the system, including disabled or invisible unowned windows, overlapped windows, and pop-up windows; but the message is not sent to child windows. Msg [in] Specifies the message to be sent. wParam [in] Specifies additional message-specific information. lParam [in] Specifies additional message-specific information. Return Value The return value specifies the result of the message processing; it depends on the message sent.
由于不同进程拥有不同的地址空间,因此SendMessage只能传递Message之类的数据,而无法传递memory。为此Microsoft定义了WM_COPYDATA消息,可以通过它将固定数据结构所保存的数据/memory发送到另一个进程,在另一个进程中取出数据/momery。
Syntax To send this message, call the SendMessage function as follows. lResult = SendMessage( // returns LRESULT in lResult (HWND) hWndControl, // handle to destination control (UINT) WM_COPYDATA, // message ID (WPARAM) wParam, // = (WPARAM) () wParam; (LPARAM) lParam // = (LPARAM) () lParam; ); Parameters wParam Handle to the window passing the data. lParam Pointer to a COPYDATASTRUCT structure that contains the data to be passed. Return Value If the receiving application processes this message, it should return TRUE; otherwise, it should return FALSE.
其中的lParam是一个指向COPYDATASTRUCT的指针。COPYDATASTRUCT中保存了memory的地址、长度信息。
Syntax typedef struct tagCOPYDATASTRUCT { ULONG_PTR dwData; DWORD cbData; PVOID lpData; } COPYDATASTRUCT, *PCOPYDATASTRUCT; Members dwData Specifies data to be passed to the receiving application. cbData Specifies the size, in bytes, of the data pointed to by the lpData member. lpData Pointer to data to be passed to the receiving application. This member can be NULL.
使用的过程中,需要在数据接收端响应WM_COPYDATA消息,MFC中通过ON_WM_COPYDATA()宏来实现。
下面举例进程A向进程B传递CString类型(Unicode)的数据。
进程A:
CString m_strFileName = L"Test.exe"; COPYDATASTRUCT copyData; copyData.cbData = m_strFileName.GetLength()*2; // Unicode-TCHAR copyData.lpData = (void*)m_strFileName.GetBuffer(copyData.cbData); m_strFileName.ReleaseBuffer(); CWnd* pWindow = FindWindow(NULL, L"B"); if (pWindow) { ::SendMessage(pWindow->m_hWnd,WM_COPYDATA, NULL, (LPARAM)©Data); }
进程B:
MESSAGE_MAP宏中增加 ON_WM_COPYDATA()
消息处理函数中提取字符串:
BOOL CXXXXDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct) { // TODO: Add your message handler code here and/or call default COPYDATASTRUCT *pcopyData; pcopyData = pCopyDataStruct; if(pcopyData) { m_strFileName.Format(L"%s", (LPCSTR)pCopyDataStruct->lpData); m_strFileName=m_strFileName.Left(pCopyDataStruct->cbData/2); } return CDialog::OnCopyData(pWnd, pCopyDataStruct); }
至此,进程B获取到了进程A传递过来的CString。
以上代码测试可用
如果有问题,欢迎探讨
mosesyuan at gmail.com