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








免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM