- C++ 黑客编程揭秘与防范(第3版)
- 冀云
- 1159字
- 2020-06-27 17:48:51
1.4.1 通过自定义消息进行进程通信
消息分为两种,一种是系统已经定义的消息,另一种是用户自定义的消息。系统已经定义的消息是从0到0x3ff,用户自定义的消息可以从0x400开始。系统中提供了一个宏WM_USER,在进行自定义消息时,在WM_USER的基础上加一个值就可以了。下面来实现一个自定义消息完成进程间通信的程序例子。
1.实现自定义消息的步骤
根据前面的介绍,我们知道,通过自定义消息进行进程间通信,只有带有窗口的进程才能完成基于消息的进程间通信。既然是进程间通信,那么就需要至少编写两个程序,一个是接收消息的服务端,另一个是发送消息的客户端,并且这两个程序都需要有窗口。
先来介绍程序的功能,在发送消息的客户端,通过自定义消息给接收消息的服务端发送两个整型的数值。接收消息的服务端,将接收到的两个数值进行简单的加法运算。接收消息的服务端在VC下,使用MFC通过自定义消息来完成进程间的通信需要3个步骤,首先要定义一个消息,其次是添加自定义消息的消息映射,最后是添加消息映射对应的消息处理函数。
首先在服务端和客户端定义一个消息,具体如下:
#define WM_UMSG WM_USER + 1
然后是在接收消息的服务端添加消息映射,如下:
BEGIN_MESSAGE_MAP(CUserWMDlg, CDialog) //{{AFX_MSG_MAP(CUserWMDlg) ON_WM_SYSCOMMAND() ON_WM_PAINT() ON_WM_QUERYDRAGICON() ON_MESSAGE(WM_UMSG, RevcMsg) //}}AFX_MSG_MAP END_MESSAGE_MAP()
在这个消息映射中,ON_MESSAGE(WM_UMSG, RevcMsg)是自定义消息的消息映射。
最后在接收消息的服务端添加自定义消息的消息响应函数。根据消息映射可以得知,消息响应函数的函数名为RevcMsg(),定义如下:
VOID CUserWMDlg::RevcMsg(WPARAM wParam, LPARAM lParam) { // …. }
2.完成自定义消息通信的代码
对于如何完成自定义消息的介绍已经介绍完了,现在来看两个程序的窗口界面,如图1-12和图1-13所示。
图1-12 自定义消息服务端(接收端)
图1-13 自定义消息客户端(发送端)
知道了两个程序的作用以及窗口的界面,那么开始对它们分别进行编码。首先来看自定义消息服务端的代码,该部分的代码比较简单。前面已经介绍了如何定义消息,如何添加消息映射,如何添加消息响应函数。现在只需要完成消息响应函数的函数体即可。消息响应函数代码如下:
VOID CUserWMDlg::RevcMsg(WPARAM wParam, LPARAM lParam) { int nNum1, nNum2, nSum; nNum1 = (int)wParam; nNum2 = (int)lParam; nSum = nNum1 + nNum2; CString str; str.Format("%d", nSum); SetDlgItemText(IDC_EDIT_REVCDATA, str); }
在消息响应的函数中有两个参数,分别是WPARAM类型和LPARAM类型。这两个参数可以接收两个4字节的参数。这里代码中接收了两个整型数值,进行相加后显示在了窗口上的编辑框中。
在发送消息端,也需要定义相同的消息类型。这里不再重复介绍,只要把响应的定义复制粘贴即可。主要看发送消息的函数,代码如下:
void CUserWMCDlg::OnBtnSend() { // 在此处添加处理程序代码 int nNum1, nNum2; nNum1 = GetDlgItemInt(IDC_EDIT_SENDDATA, FALSE, FALSE); nNum2 = GetDlgItemInt(IDC_EDIT_SENDDATA2, FALSE, FALSE); HWND hWnd = ::FindWindow(NULL, "自定义消息服务端"); ::SendMessage(hWnd, WM_UMSG, (WPARAM)nNum1, (LPARAM)nNum2); }
通过SendMessage()函数完成了发送,同样也非常简单。在SendMessage()函数中,通过第3个参数和第4个参数将两个整型值发送给了目标的窗口。
从自定义消息的例子中可以看出,自定义消息对于进程间的通信只能完成简单的数值型的传递,对于类型复杂的数据的通信就无法完成了。那么,通过消息是否能完成字符串等数据的通信传递呢?答案是肯定的。接下来看使用WM_COPYDATA消息完成进程间通信的例子。