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消息完成进程间通信的例子。