分享

VC进程间通信之消息传递PostMessge()或SendMessage()...

 灞河之滨 2020-10-19

1.  进程内消息:

(1). 只传消息码

(2). 传送消息串

  1. 发送端:
  2. void CTestDlg::OnBnClickedButtonSend()
  3. {
  4. CString* msg = new CString("发送的字符串");
  5. ::SendMessage(m_hWnd,WM_USER+1,0,(LPARAM)msg);
  6. delete msg;
  7. }
  8. 接收端:
  9. afx_msg HRESULT OnClickBtn(WPARAM,LPARAM);
  10. BEGIN_MESSAGE_MAP
  11. ON_MESSAGE(WM_USER+1,OnClickBtn)
  12. END_MESSAGE_MAP()
  13. HRESULT CSendMessageDlg::OnClickBtn1(WPARAM wParam,LPARAM lParam)
  14. {
  15. CString* rmsg = (CString*)lParam;
  16. MessageBox(*rmsg);
  17. return TRUE;
  18. }

 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 结构体

  1. LRESULT copyDataResult; //copyDataResult has value returned by other app
  2. CWnd *pOtherWnd = CWnd::FindWindow(NULL, strWindowTitle);
  3. if (pOtherWnd)
  4. {
  5. COPYDATASTRUCT cpd;
  6. cpd.dwData = 0;
  7. cpd.cbData = strDataToSend.GetLength(); //data length
  8. cpd.lpData = (void*)strDataToSend.GetBuffer(cpd.cbData); //data buffer
  9. copyDataResult = pOtherWnd->SendMessage(WM_COPYDATA,(WPARAM)AfxGetApp()->m_pMainWnd->GetSafeHwnd(),(LPARAM)&cpd);
  10. strDataToSend.ReleaseBuffer();
  11. }
  12. else
  13. {
  14. AfxMessageBox("Unable to find other app.");
  15. }

(2)添加消息

The other app should handle the WM_COPYDATA message in the following manner

  1. BEGIN_MESSAGE_MAP(CMyWnd, CWnd)
  2. ...
  3. ON_WM_COPYDATA()
  4. ...
  5. END_MESSAGE_MAP()

(3)消息处理

  1. BOOL CMyWnd::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
  2. {
  3. CString strRecievedText = (LPCSTR) (pCopyDataStruct->lpData);
  4. return CMyWnd::OnCopyData(pWnd, pCopyDataStruct);
  5. }

五、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中发送消息:

  1. #define WM_MYMESSAGE WM_USER + 1
  2. //目标进程的窗口类名(可通过Spy++工具查看)和窗口名
  3. CWnd *pWnd = CWnd::FindWindow("#32770", "MfcTest");
  4. if (NULL != pWnd)
  5. {
  6. pWnd->PostMessage(WM_MYMESSAGE, NULL, NULL);
  7. }
  8. 或者:
  9. HWND hWnd = ::FindWindow("#32770", "MfcTest");
  10. if (NULL != hWnd)
  11. {
  12. ::PostMessage(hWnd, WM_MYMESSAGE, NULL, NULL);
  13. }
项目2中接收消息:

.h中声明:

afx_msg LRESULT OnMyMessage(WPARAM wp, LPARAM lp);

.cpp中定义:

  1. BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
  2. ...
  3. ON_MESSAGE(WM_MYMESSAGE, OnMyMessage)
  4. ...
  5. END_MESSAGE_MAP()
  1. LRESULT CMfcTestDlg::OnMyMessage(WPARAM wp, LPARAM lp)
  2. {
  3. AfxMessageBox("Hello World");
  4. return 0;
  5. }

说明:

使用PostMessage或SendMessage均可,区别在于SendMessage阻塞,直到目标窗口程序处理完消息再返回,而PostMessage是将一个消息寄送到一个线程的消息队列后就立即返回。通常使用PostMessage,如果为了探测目标进程是否存在,则用SendMessage比较好。

方法2: 消息接收端采用PreTranslateMessage()来处理

发送端代码:

  1. #define WM_MYMESSAGE WM_USER + 1
  2. //目标进程的窗口类名(可通过Spy++工具查看)和窗口名
  3. CWnd *pWnd = CWnd::FindWindow("#32770", "MfcTest");
  4. if (NULL != pWnd)
  5. {
  6. pWnd->PostMessage(WM_MYMESSAGE, NULL, NULL);
  7. }
  8. 或者:
  9. HWND hWnd = ::FindWindow("#32770", "MfcTest");
  10. if (NULL != hWnd)
  11. {
  12. ::PostMessage(hWnd, WM_MYMESSAGE, NULL, NULL);
  13. }

接收端代码:

.h声明

BOOL CMfcTestDlg::PreTranslateMessage(MSG* pMsg);

.cpp定义

  1. #define WM_MYMESSAGE WM_USER + 1
  2. BOOL CMfcTestDlg::PreTranslateMessage(MSG* pMsg)
  3. {
  4. if (pMsg->message == WM_USER + 1)
  5. {
  6. AfxMessageBox("Hello World");
  7. }
  8. return CDialog::PreTranslateMessage(pMsg);
  9. }


说明:

这里将接收端处理放在PreTranslateMessage 中, 因此发送端必须选择 PostMessage, 因为SendMessage消息不放进消息队列, PreTranslateMessage里不能收到这个消息。



    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多