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