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



    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里不能收到这个消息。


    

    
    
  • 相关阅读:
    Linux中使用mysqldump对MySQL数据库进行定时备份
    Linux备份数据库,mysqldump命令实例详解
    laravel 怎么获取public路径
    laravel 返回值
    [Deep-Learning-with-Python]机器学习基础
    [Deep-Learning-with-Python]基于Keras的房价预测
    [Deep-Learning-with-Python]基于Kears的Reuters新闻分类
    基于Keras的imdb数据集电影评论情感二分类
    [Deep-Learning-with-Python]神经网络入手学习[上]
    [Deep-Learning-with-Python]神经网络的数学基础
  • 原文地址:https://www.cnblogs.com/claireyuancy/p/6785512.html
Copyright © 2020-2023  润新知