1. 进程内消息:
(1). 只传消息码
(2). 传送消息串
发送端: void CTestDlg::OnBnClickedButtonSend() { CString* msg = new CString("发送的字符串"); ::SendMessage(m_hWnd,WM_USER+1,0,(LPARAM)msg); delete msg; } 接收端: afx_msg HRESULT OnClickBtn(WPARAM,LPARAM); BEGIN_MESSAGE_MAP ON_MESSAGE(WM_USER+1,OnClickBtn) END_MESSAGE_MAP() HRESULT CSendMessageDlg::OnClickBtn1(WPARAM wParam,LPARAM lParam) { CString* rmsg = (CString*)lParam; MessageBox(*rmsg); return TRUE; }
2. 进程间通讯:
PostMessge或者SendMessage()实现进程间通讯
(1)两个不同的进程不能用上面的方法,当然只发送消息不发内容是可以的。
(2)两个进程由于使用的是相互独立的两个虚拟内存空间,同一地址对不同的进程来说并不一定指向同一物理内存,内容也就不一定一样,因此不同进程无法通过传地址的方式传递字符串(但是同一进程下的不同线程是可以的)
2.解决办法
发送WM_COPYDATA消息在进程间传送数据
(1)发送消息
The exchange of data is performed by finding the other application (using FindWindow) and sending a WM_COPYDATA message to that window
使用FindWindow找到窗口,然后发送WM_COPYDATA消息,字符串附加到COPYDATASTRUCT 结构体
LRESULT copyDataResult; //copyDataResult has value returned by other app CWnd *pOtherWnd = CWnd::FindWindow(NULL, strWindowTitle); if (pOtherWnd) { COPYDATASTRUCT cpd; cpd.dwData = 0; cpd.cbData = strDataToSend.GetLength(); //data length cpd.lpData = (void*)strDataToSend.GetBuffer(cpd.cbData); //data buffer copyDataResult = pOtherWnd->SendMessage(WM_COPYDATA,(WPARAM)AfxGetApp()->m_pMainWnd->GetSafeHwnd(),(LPARAM)&cpd); strDataToSend.ReleaseBuffer(); } else { AfxMessageBox("Unable to find other app."); }
(2)添加消息
The other app should handle the WM_COPYDATA message in the following manner
BEGIN_MESSAGE_MAP(CMyWnd, CWnd) ... ON_WM_COPYDATA() ... END_MESSAGE_MAP()
(3)消息处理
BOOL CMyWnd::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct) { CString strRecievedText = (LPCSTR) (pCopyDataStruct->lpData); return CMyWnd::OnCopyData(pWnd, pCopyDataStruct); }
五、PostMessage 和SendMessage的区别
(1). PostMessage 和SendMessage的区别主要在于是否等待其他程序消息处理完成。
PostMessage只是把消息放入队列,不管其他程序是否处理都返回,然后继续执行。
而SendMessage则必须等待其他程序处理消息完成后才返回继续执行。由于SendMessage消息不放进消息队列, 所以PreTranslateMessage里无法收到其消息。
(2). 这两个函数的返回值也不同
原型:
BOOL PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);
LRESULT SendMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM IParam);
SendMessage的返回值表示其他程序消息处理函数的返回值(如return 10, 则long nRet = SendMessage(...) = 12)。
PostMessage的返回值仅表示PostMessage函数执行是否成功,成功返回非零,否则返回零。
举例如下(只传消息码):
方法1: PostMessge或者SendMessage()消息机制
项目1中发送消息:
#define WM_MYMESSAGE WM_USER + 1 //目标进程的窗口类名(可通过Spy++工具查看)和窗口名 CWnd *pWnd = CWnd::FindWindow("#32770", "MfcTest"); if (NULL != pWnd) { pWnd->PostMessage(WM_MYMESSAGE, NULL, NULL); } 或者: HWND hWnd = ::FindWindow("#32770", "MfcTest"); if (NULL != hWnd) { ::PostMessage(hWnd, WM_MYMESSAGE, NULL, NULL); }项目2中接收消息:
.h中声明:
afx_msg LRESULT OnMyMessage(WPARAM wp, LPARAM lp);
.cpp中定义:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd) ... ON_MESSAGE(WM_MYMESSAGE, OnMyMessage) ... END_MESSAGE_MAP()
LRESULT CMfcTestDlg::OnMyMessage(WPARAM wp, LPARAM lp) { AfxMessageBox("Hello World"); return 0; }
说明:
使用PostMessage或SendMessage均可,区别在于SendMessage阻塞,直到目标窗口程序处理完消息再返回,而PostMessage是将一个消息寄送到一个线程的消息队列后就立即返回。通常使用PostMessage,如果为了探测目标进程是否存在,则用SendMessage比较好。
方法2: 消息接收端采用PreTranslateMessage()来处理
发送端代码:
#define WM_MYMESSAGE WM_USER + 1 //目标进程的窗口类名(可通过Spy++工具查看)和窗口名 CWnd *pWnd = CWnd::FindWindow("#32770", "MfcTest"); if (NULL != pWnd) { pWnd->PostMessage(WM_MYMESSAGE, NULL, NULL); } 或者: HWND hWnd = ::FindWindow("#32770", "MfcTest"); if (NULL != hWnd) { ::PostMessage(hWnd, WM_MYMESSAGE, NULL, NULL); }
接收端代码:
.h声明
BOOL CMfcTestDlg::PreTranslateMessage(MSG* pMsg);
.cpp定义
#define WM_MYMESSAGE WM_USER + 1 BOOL CMfcTestDlg::PreTranslateMessage(MSG* pMsg) { if (pMsg->message == WM_USER + 1) { AfxMessageBox("Hello World"); } return CDialog::PreTranslateMessage(pMsg); }
说明:
这里将接收端处理放在PreTranslateMessage 中, 因此发送端必须选择 PostMessage, 因为SendMessage消息不放进消息队列, PreTranslateMessage里不能收到这个消息。