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

Posted claireyuancy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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里不能收到这个消息。


??

??
??

以上是关于VC进程间通信之消息传递PostMessge()或SendMessage()的主要内容,如果未能解决你的问题,请参考以下文章

IPC进程间通信之四数据复制消息WM_COPYDATA

VC++ 进程间的通信

linux进程间通信之Posix消息队列

进程间通讯之有名管道

python基础之进程间通信进程池协程

在 Windows 7 中使用 VC++ 和 C# 中的 MemoryMappedFiles 或命名管道进行进程间通信