windows进程通信 -- WM_COPYDATA消息
WM_COPYDATA消息,在win32中用来进行进程间的数据传输。
typedef struct tagCOPYDATASTRUCT { // cds DWORD dwData; DWORD cbData; PVOID lpData; } COPYDATASTRUCT;
其中dwData为32位的自定义数据, lpData为指向数据的指针,cbData为lpData指针指向数据的大小(字节数)。
一般推荐用SendMessage函数进行发送,这样就能确保在接收方复制数据前避免发送方能修改或删除数据;
LRESULT SendMessage( HWND hWnd, // handle of destination window UINT Msg, // message to send WPARAM wParam, // first message parameter LPARAM lParam // second message parameter );
这里:
hWnd:为接收进程的窗体句柄;
Msg:WM_COPYDATA;
wParam:为发送进程的窗体句柄;
lParam:为指向COPYDATASTRUCT数据结构的指针;
这里需要注意的:传输的COPYDATA数据在发送后要避免被发送进程中的其他线程修改,其次要确保被传输的数据中没有包含接收进程无法访问的对象的指针或引用。比如:发送进程自身的HDC、HBITMAP之类的东西,它们对于接收进程来说是无效的。另外,接收进程窗体句柄可以通过FindWindow函数获取:
const char szDlgTitle[] = "ReceiveProcess"; HWND hRecvWindow = ::FindWindow(NULL, szDlgTitle);
这里的“ReceiveProcess”为接收进程的名字;
同时,接收数据的进程中,首先在消息映射表中增加WM_COPYDATA消息映射,然后定义消息映射函数,其函数的格式为:
BOOL CCanCollectorDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
....
}
主要代码如下:(这里发送进程发送当前的时间给接收进程)
发送进程:
void CProcessCommDlg::OnBTNStart1() { const char szDlgTitle[] = "ReceiveProcess"; HWND hSendWindow =this->GetSafeHwnd(); HWND hRecvWindow = ::FindWindow(NULL, szDlgTitle); COPYDATASTRUCT CopyData; char szSendBuf[100]; time_t timenow; time(&timenow); sprintf(szSendBuf, "%s", ctime(&timenow));//注意,ctime()返回的字符串后面带了'\n' CopyData.dwData = 0; CopyData.cbData = strlen(szSendBuf); szSendBuf[CopyData.cbData - 1] = '\0'; CopyData.lpData = szSendBuf; ::SendMessage(hRecvWindow, WM_COPYDATA, (WPARAM)hSendWindow, (LPARAM)&CopyData); printf("%s\n", szSendBuf); }
接收进程:
BEGIN_MESSAGE_MAP(CCanCollectorDlg, CDialog) //{{AFX_MSG_MAP(CCanCollectorDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_WM_COPYDATA() //}}AFX_MSG_MAP END_MESSAGE_MAP() ........ BOOL CCanCollectorDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct) { char szBuffer[300]; memset(szBuffer, 0, sizeof(szBuffer)); sprintf(szBuffer, "dwData:%d cbData:%d\r\nlpData:0x%08x = %s\r\n\r\n", pCopyDataStruct->dwData, pCopyDataStruct->cbData, (PVOID)pCopyDataStruct->lpData, (char*)pCopyDataStruct->lpData); return CDialog::OnCopyData(pWnd, pCopyDataStruct); }