MFC--自定义消息

在windows程序中,消息是一个重要的概念,最常见的消息一般都是以WM_开头,WM就是window message,窗口消息的缩写,通过处理标准的windows消息,我们可以改变窗口的外观,如使用WM_ERASEBKGND消息可以改变窗口默认的窗口背景,窗口每次需要绘制窗口的背景的时候,就会发送一次这个消息,如果我们处理这个消息,我们就可以绘制我们自己的特性化的背景,如果不处理,默认窗口过程就会处理,绘制背景。通过处理标准的windows消息,我们可以对用户的输入做出响应,如WM_LBUTTONDOWN,当鼠标按下的时候,就可以对用户的操作作出响应,通过命令消息WM_COMMAND消息,可以获取来自菜单,按钮的命令。另外,控件还有自己的notification消息,当控件的状态发生改变的时候,如点击按钮,点击编辑框,选择一个列表框项目时,就会发送相应的消息,通过处理消息,就可以对获取控件的一些消息,做出一些处理。在sdk中还有一种消息,也是用于控件的,也是通过发送消息来控制控件的属性和操作,而这个在MFC中变成了成员函数,但是底层的原理还是一样的。消息的作用还有很多,我们不能单一的去理解消息这个概念,一方面,我们可以通过阅读msdn可以深入的学习消息,另一方面,我们可以通过在使用的过程中,加深对消息的理解。除了使用上面说的这些windows提供的预定义消息(系统消息)之外,我们也可以使用我们自定义的消息。

每个消息有一个ID,对于自定义消息,我们在定义的时候,也要定义一个ID,而这个ID的范围是有要求的,可以是WM_USER (0x0400) 到 0x7FFF,也可以是 WM_APP (0x8000) 到0xBFFF,别的ID范围呢,系统保留。在使用的时候,通常都是以WM_USER+X,WM_APP+X或是在定义消息ID的时候,有两种方法:

第一种方法是通过常量声明幅值的方法,也就是常量的使用方法,因为一个消息的ID就是一个常量,确定之后,就不能改变,因此,可以使用定义常量的方法来为一个消息附上ID,如下:

const UINT WM_MYMESSAGE1=WM_APP+1;

第二种方法是通过#define,如下:

#define WM_MYMESSAGE2 WM_APP+2

通过这两种方法,我们就可以在为一个消息指定ID。下面是要说说,上面这两句定义消息ID的表达式所放的位置的不同所产生的使用方法的不同。下面以实例来说明:

第一种情况,当我把定义消息ID的表达式放在了头文件MyView.h中

MFC--自定义消息_第1张图片

当我在SINView.cpp文件中接收和处理这两个消息时,必须事先包含声明两个消息ID的头文件,这里是MyView.h。否则,在cpp中处理的时候,就是出现语法错误,提示未声明的标示符。

第二种情况,如果我们由于一些原因,不能包含声明消息ID的头文件,例如,如果我们包含了,就会出现互相包含的情况,就会造成错误,或是,将在发送这个消息的cpp文件和接受处理这个消息的cpp文件中定义这两个消息的ID,那么这个时候,我们必须在两个地方声明和幅值消息ID,一个地方是发送的类的源文件或头文件中,另一个地方是接收和处理这个自定义消息的源文件中。例如,WM_MYMESSAGE3,我在MyView.h或是MyView.cpp中进行声明,因为我要从MyView.cpp中发送这个消息,如图:

MFC--自定义消息_第2张图片

在接收消息的地方,我再次定义一次,可以直接复制上次定义的,我要在SINView.cpp中接收和处理,于是在这个文件的开头,如下图:


现在已经定义好了消息的ID,接下来是发送消息,发送消息,一般是是用SendMessage和PostMessage,SendMessage必须要等到这个消息被处理并返回之后才会结束执行,否则会一直等待,如果消息一直得不到处理,函数一直等待,就会造成发送消息的线程阻塞。PostMessage是将消息发送之后,就立即返回,不管消息是否到达目的地,处理。如果在单线程程序中,我们最好是用PostMessage,用SendMessage容易造成线程锁死。另外,在MFC中使用这两个函数,如果直接使用,第一个参数就是要发送的消息,这样只能向本窗口发送消息,如果在MFC中使用::PostMessage,这样就是使用的是win32函数的api,第一个参数是目标窗口句柄,就可以向任意窗口发送消息。

下面说说如何处理发送的消息,首先介绍一种最为简单的处理方法,这种方法和在win32 sdk中的窗口过程一样,通过switch/case语句来处理.在MFC窗口类都有一个WindowProc虚函数,当这个窗口的消息进入这个窗口的消息映射之前,会首先通过这个虚函数,因此,我们在这里就可以拦截处理我们的自定义消息,甚至是别的任何消息,当然,标准窗口消息仍然是推荐使用MFC的消息映射的方法来处理。如下图:

MFC--自定义消息_第3张图片

使用这种方法,有一点很重要,那就是最后那一句return语句:return CView::WindowProc(message, wParam, lParam);这样保证别的消息可以正确处理。这种处理方式和win32 sdk中的窗口过程处理消息的方式是一样的。

接着介绍一种MFC标准的自定义消息处理的方式,也就是是用ON_MESSAGE宏。使用这种方式,就和我的博文"MFC-消息机制"中描述的消息处理方式一样,要使用这种处理方式,首先要声明一个消息响应函数原型,接着添加消息映射,最后实现消息响应函数。我们一步一步来看,首先看ON_MESSAGE宏的原型:

ON_MESSAGE(message, memberFxn)

第一个参数是消息ID,第二个参数消息响应函数。现在,针对WM_MYMESSAGE3消息,我们使用这种处理方式。首先在CSINView类中声明一个消息响应函数:

afx_msg LRESULT OnMyMessage3(WPARAM wParam, LPARAM lParam);

消息响应函数的名称由自己确定,这里我使用的是OnMyMessage3。在声明这个消息响应函数的时候,一般就是按照这个样式,而且一般声明为protected。

接着是消息添加消息映射,使用ON_MESSAGE,如下:

MFC--自定义消息_第4张图片

最后是实现消息响应函数,在SINView.cpp中,如下:

MFC--自定义消息_第5张图片

通过ON_MESSAGE宏,当窗口接收到消息的时候,就会自动调用我们的消息响应函数了。

以上就阐述了一下,在MFC自定义消息的使用方法,下面是效果图:

MFC--自定义消息_第6张图片

最后在说说消息过滤的问题,使用过win32 sdk编写程序的人都知道,可以在使用while从消息队列中获取消息的时候,在派发消息到窗口之前,可以做一个消息过滤,在MFC这里也可以,CWinApp有一个虚函数CWinApp::PreTranslateMessage,这个虚函数就是消息循环获取消息,派发之前,就调用这个虚函数,我们就可以在这个虚函数中,拦截过滤一些消息,主要是通过这个虚函数的参数,一个消息结构体,来判断要过滤的消息。一个是判断句柄,一个是判断消息id。

本文中涉及到的信息,如有疑问,请参考msdn。

author email:[email protected] 

本文代码:http://download.csdn.net/detail/xinzhiyounizhiyouni/6680781 

windows7 vs2010环境下

 

你可能感兴趣的:(mfc)