MFC消息映射详解

消息:主要指由用户操作而向应用程序发出的信息,也包括操作系统内部产生的消息。例如,单击鼠标左按钮,windows将产WM_LBUTTONDOWN消息,而释放鼠标左按钮将产生WM_LBUTTONUP消息,按下键盘上的字母键,将产生WM_CHAR消息。

消息处理:在MFC中,每个专门的处理函数单独处理每个消息。消息处理函数通常是某一类的成员函数,编写消息处理函数是编写框架应用程序的主要任务。可以使用ClassWizard创建消息处事函数,然后从Classwizard直接跳到源文件消息处理函数,编写处理代码。

消息映射:可以接收消息和命令的所有框架类都有自已的消息映射。框架利用消息映射把消息、命令与它们的处理函数链接起来。从CCmdTarget类派生的任何类都可以有消息映射。虽然叫作消息映射,但消息映射既可以处理消息,也可以处理命令。

与传统的DOS不同,WINDOWS采用的是基于消息的时间驱动形式。当应用程序开始执行时,Windows为该程序创建一个消息队列(message queue,用以存放发给该程序可能创建的各种不用窗口的消息,消息结构为:

typedef struct tagMSG { // msg  

   HWND hwnd;//用以标识接受消息的窗口的窗口句柄

   UINT message;//消息标识号

   WPARAM wParam;//消息参数

   LPARAM lParam;//消息参数

   DWORD time;//邮寄消息的时间

   POINT pt;//在屏幕坐标下坐标位置

} MSG;

Windows提供了GetMessagePostMessageSeekMessge这样的获得消息、发送消息、查找消息的函数,用来处理不同消息来实现程序的目标。一条消息一条消息的处理很繁琐,为了提高效率,MFC将这些消息及函数封装起来,这就出现了消息映射表和消息映射宏这样的概念。

消息映射表

例如,用户在按下鼠标左键时,Windows会发出WM_LBUTTONDOWN消息。MFC提供了一种消息映射机制将用户单击左键发出的WM_LBUTTONDOWN消息和一个函数联系在一起。具体代码为:

afx_msg void OnLButtonDown(UINT nFlags,CPoint point);  //语句的位置在头文件消息声明宏(DECLARE_MESSAGE_MAP)内

ON_WM_LBUTTONDOWN();        //这条语句的位置是在实现文件的消息宏(BEGIN_MESSAGE_MAP宏和END_MESSAGE_MAP之间)内

通过上面两行代码已经建立了消息的映射,用户只需要将所要实现功能的代码写入下面的函数内即可:

void CDlg::OnLuttonDown(UINT nFlags,CPoint point){

//添加代码

//CDlg::OnLuttonDown(nFlags,point);

}

MFC中每一个消息都对应一个函数,这样一对一的关系罗列出来就是一个表,如果开发人员需要处理某条消息,只要在消息对应的处理函数中写入代码即可。

消息映射表在MFC中主要是通过三个宏来实现的。这三个宏分别是:

DECLARE_MESSAGE_MAP消息的声明宏、

BEGIN_MESSAGE_MAP宏、

END_MESSAGE_MAP宏。

消息映射宏

消息映射宏主要有命令消息映射宏、控件窗体消息映射宏、普通窗口消息映射宏、用户自定义消息映射宏。

消息映射宏中有带有COMMAND字样的都是用来处理命令消息的。命令消息主要是通过单击菜单及单击按钮产生的。命令消息在CCmdTarget类是没有处理函数的,也就是说不在消息映射表内。菜单项和按钮还有其他一些控件都有其ID值,命令消息映射宏主要就是将菜单、按钮和其他一些控件的ID和处理函数映射起来。命令消息的添加也是通过MFCClassWizard来完的。

在映射宏中有几个是带REFLECT字样的,这些都是用来处理反射消息的映射宏。反射消息是指子控件向父控件发送消息,而父控件并不处理该消息,而是把消息返回给子控件,让子控件处理这个消息,这就形成了一去一回的反射过程。反射消息主要是在CladdWizard想到的MessageMap选项卡中,Mesage栏里一些前面带“=”的消息。

windows消息组成结构

windows消息由消息号和参数组成:

  消息号:windows操作系统通过32整数标识一条windows消息,称为消息号。windows消息号具有三个特点:

(1)唯一性:唯一性指对于windows操作系统中的每一条消息都有一个且只有一个消息号与它相对应。由于windows操作系统通过消息激活相应的过程,因此消息的标识必须是唯一的。

(2) 直观性:消息号在形式上表现为消息名,消息名往住直观地说明了消息的产生方式和类型,例如消息名WM_LBUTTONDOWN直观地表示了单击产生的消息。

  (3)可自定义性:windows系统定义了一些消息号和消息名,程序员可以运用这些消息,也可以使用自已定义的窗口的消息。形式如下: #define 消息名 消息号

  注意,为了不与现有的windows系统消息相冲突,在消息号的定义中通常采用如下:

  WM_USER+n   WM_USERwindows操作系统定义的用户消息起始值,程序员必须从该起始值后选取消息号,例如自定义消息名为“MESSAGE_1”和 “MESSAGE_2”,可采用如下形式:

  #define MESSAGE_1 WM_USER+1

  #DEFINE MESSAGE_2 WM_USER+2

  参数:windows的消息具有以下两个参数:字参数(wParam);长参数(lParam)。字参数和长参数都是32位整数,用于提供消息的附带消息,是消息传递过程中参数的载体。附加信息的消息号取决于消息号。

消息种类

消息主要有三种类型,即windows消息,命令消息和控件通知。按消息的产生可以分为四类:

  *(1)外界输入事件产生的消息; *(2)windows系统向应用程序发出的消息

  *(3)应用程序之间发送的消息; *(4)其他

  根据产生消息的对象,可以进一步将消息分为以下几类:

  *(1)窗口管理消息  包括激活基本窗口操作的消息,如关闭、最大化等。

  *(2)初始化消息  应用程序、窗口、控件等对象初始化的消息。

  *(3)输入消息  包括键盘、鼠标、绘图仪等处部输入工具的输入消息。

  *(4)系统消息  windows系统内部消息。

  *(5)剪贴板消息  操作剪贴板时产生的消息。

  *(6)系统信息消息  用于系统信息发送和处理的消息。

  *(7)控件处理消息  操作控件时产生的消息。

  *(8)控件通知消息  系统采用空件通知消息向控件发送消息。

  *(9)滚动条消息  操作滚动条时产生的消息

  *(10)非用户区消息  非用户区产生的消息

  *(11)MDI消息  用于多文档操作的消息

  *(12)DDE消息  用于动态数据交换的消息。

  *(13)应用程序自定义的消息等等。

windows消息:除WM_COMMAND外,所有以WM_开头的消息都是windows消息。windows消息由窗口和视图处理。这类消息通常含有用于确定如何对消息进行处理的一些参数。

控件消息:控件通知包含从控件和其他子窗口传递给父窗口的WM_COMMAND通知消息。例如,当用户改变编辑控件中的文本时,编辑控件将发送给父窗(例如对话框)一条含有EN_EXCHANGE控件通知码的WM_COMMAND消息。窗口的消息处理函数将以适当的方式对通知消息作出响应,如获取编辑框中的文本等。像其他标准windows消息一样,控件通知消息由窗口和视图进行处理。但是如果用户单击控件按钮时发出的BN_CLICKED控件通知消息将作为命令消息来处理。

命令消息:命令消息包括来自用户界面对象的WM_COMMAND通知消息。菜单项、工具栏按钮和加速键都是可以产生命令的用户界面对象。每个这样的对象都有一个 ID。通过给对象和命令分配给同一个ID可以把用户界面对象和命令联系起来。命令是被作为特殊的消息来处理的。

通常,命令ID是以其表示的用户界面对象的功能来命名的。例如,Edit菜单中的Copy命令就可以用ID_EDIT_COPY来表示。MFC类库预定义了某些命令ID(如ID_EDIT_PASTEID_FILE_OPEN等等)。其他命令ID则要编程人员自已定义,所有预定义命令ID的列表,参见 AFXRES.H文件。

命令消息的处理和其他消息的处理不同。命令消息可以被更广泛的对象(如文档、文档模板、应用程序对象、窗口和视图等)处理。windows把命令发送给多个候选对象,称为命令目标。通常其中一个对象有针对该命令的处理函数。处理函数处理命令的方法和处理windows消息的方法是一样的,但调用机制不一样。

常用消息

1WM_LBUTTONDOWN

  产生:单击。

  参数:wParam:包含一个整数值,以标识鼠标键的按下状态。鼠标的按下标识及说明

  MK_LBUTTON  标识按下鼠标左键

  MK_MBUTTON  标识按下鼠标中键

  MK_RBUTTON  标识按下鼠标右键

  lParam:长参数lParam的低字位包含当前坐标的x坐标,在高字节包含当前坐标的Y坐标。

    相似的消息有:WM_LBUTTONUPWM_RBUTTONDOWNWM_RBUTTONUPWM_LBUTTONDBLCLKWM_RBUTTONDBLCLK

2WM_KEYDOWN

  产生:按下一个非系统键的时候产生该事件,系统键是指实现系统操作的组合键,例如,Alt与某个功能键的组合以实现菜单操作等。

  参数:wParam:按下键的虚拟键盘码,虚拟键码用来标识按下或者释放的是哪个键,例如功能键F1的虚拟键码在windows.h文件中定义为VK_F1

  lParam:长参数中记录了按键的重复次数,扫描码、转移代码、先前键的状态等信息。

  相似的消息有WM_KEYUP:放开按下的非系统键时产生的事件。

3WM_CHAR

  产生:按一个非系统键时产生。

  参数:wParam:所按下的键的ASCII码。lParam:长参数中记录了按键的重复次数,扫描码、转移代码、先前键的状态等信息。

4WM_CREATE

  产生:由CreateWindow函数发出,创建窗口。

  参数:wParam:没用。lParam:包含一个指向CREATESTRUCT数据结构的指针,该结构是传递给CreateWindow函数的参数的副本。

5WM_CLOSE

  产生:当关闭当前窗口时产生。

  参数:wParam:未用。lParam:未用。

6WM_DESTROY

  产生:当窗口要销毁时由DestroyWindow函数发出。

  参数:wParam:没用到。lParam:没用到。

7WM_QUIT

  产生:退出应用程序时由PostQuitMessage函数发出。

  参数:wParam:含有退出代码,退出代码标识应用程序退出运行时的有关信息。lParam:未用。

8WM_COMMAND

  产生:用户与窗口或控件交互时,控件向其窗口发送WM_COMMAND消息。该消息的wParam参数的低字节中包含子窗口(控件)的标识值ID,高字节中包含子窗口向父窗口发出的通知代码,lParam参数中包含控件子窗口句柄。

9WM_PAINT

  用户改变窗口大小或拖动窗口,系统向应用程序发送WM_PAINT消息,WM_PAINT消息调用BeginPaint函数。

消息处理函数

1windows消息和控件通知的处理函数

  windows消息和控件通知都是由派生于CWnd的窗口类对象处理的。它们包括CFrameWndCMDIFrameWnd、 CMDIChildWndCViewCDialog以及从这些派生的用户自定义的类。这样的类对象封装了windows窗口句柄HWND

  windows消息和控件通知都有默认的处理函数,这些函数在CWnd类中进行了预定义,MFC类库以消息名为基础形成这些处理函数的名称,这些处理函数的名称都以前缀"On"开始。有的处理函数不带参数,有的则有几个参数;有的还有除void以外的返回值类型。CWnd中消息处理函数的说明都有 afx_msg前缀。关键字afx_msg用于把处理函数和其他CWnd成员函数区分开来。例如,消息WM_PAINT的处理函数在CWnd中被声明成:afx_msg void OnPaint();

  windows消息常见的有鼠标消息(如WM_LBUTTONDOWN)消息)、键盘字符消息(WM_CHAR消息)、键盘按键消息(WM_KEYDOWN)、窗口重画消息WM_PAINT,水平和垂直条滚动消息WM_HSCROLLWM_VSCROLL)以及系统时钟消息 WM_TIMER等。

2、命令消息的处理函数

  由于用户界面的对象是用户自已定义的,每个应用程序的用户界面对象千差万别,所以对用户界面对象的命令消息没有默认的处理函数。如果某条命令直接影响某个对象,则应该让这个对象来处理这条命令。例如FILE菜单上的Open命令当然与应用程序有关:应用程序打开一个特定的文档来响应该命令。所以,Open 命令的处理函数是应用程序类的一个成员函数。

  把命令消息映射成处理函数时,ClassWizard以命令ID来命名处理函数,可以接受、修改、或替换推荐使用的名字。例如,Edit菜单项的Cut命令,对应ID就是ID_EDIT_CUT,处理函数被命名成:afx_msg void OnEditCut();

  此外,对于控件按钮的BN_CLICKED通知消息,其处理函数可以被命名为:

  afx_msg void OnClickedUseAsDefault();

  命令消息的处理函数没有参数值,也不返回值。

消息映射

  用MFC Application Wizard 创建应用程序框架时,AppWizard为创建的每个命令目标类(包括派生的应用程序对象、文档、视图、和边框窗口等)编写一个消息映射。每个命令目标类的消息映射存在相应的.cpp文件中。可以在AppWizard创建的基本消息映射的基础上,使用ClassWizard为每个类将处理的消息和命令添加一些条目。例如,对于应用程序类,MFC AppWizard创建的基本消息映射为:

  BEGIN_MESSAGE_MAP(CTextEditApp,CWinApp)

  //{{AFX_MSG_MAP(CTextEditApp)

  ON_COMMAND(ID_APP_ABOUT,OnAppAbout)

  //注:ClassWizard将在此处添加和删除消息映射宏

  //不要编辑这些生成的代码块

  //}}AFX_MSG_MAP

  //基于标准文件的文档命令(新建和打开)

  ON_COMMAND(ID_FILE_NEW,CWinApp::OnFileNew)

  ON_COMMAND(ID_FILE_OPEN,CWinApp::OnFileOpen)

  //标准的打印设置命令

  ON_COMMAND(ID_FILE_PRINT_SETUP,CWinApp::OnFilePrintSetup)

  END_MESSAGE_MAP()

融合MFC各种消息的描叙与实现····· 消息映射的实现   Windows消息概述   Windows应用程序的输入由Windows系统以消息的形式发送给应用程序的窗口。这些窗口通过窗口过程来接收和处理消息,然后把控制返还给Windows。   消息的分类   队列消息和非队列消息   从消息发送途径上看,消息分两种:队列消息和非队列消息。队列消息送到系统消息队列,然后到线程消息队列;非队列消息直接送给目的窗口过程。   这里,对消息队列阐述如下:   Windows维护一个系统消息队列(System message queue),每个GUI线程有一个线程消息队列(Thread message queue)。   鼠标、键盘事件由鼠标或键盘驱动程序转换成输入消息并把消息放进系统消息队列,例如WM_MOUSEMOVE、WM_LBUTTONUP、WM_KEYDOWN、WM_CHAR等等。Windows每次从系统消息队列移走一个消息,确定它是送给哪个窗口的和这个窗口是由哪个线程创建的,然后,把它放进窗口创建线程的线程消息队列。线程消息队列接收送给该线程所创建窗口的消息。线程从消息队列取出消息,通过Windows把它送给适当的窗口过程来处理。   除了键盘、鼠标消息以外,队列消息还有WM_PAINT、WM_TIMER和WM_QUIT。   这些队列消息以外的绝大多数消息是非队列消息。   系统消息和应用程序消息   从消息的来源来看,可以分为:系统定义的消息和应用程序定义的消息。   系统消息ID的范围是从0到WM_USER-1,或0X80000到0XBFFFF;应用程序消息从WM_USER(0X0400)到0X7FFF,或0XC000到0XFFFF;WM_USER到0X7FFF范围的消息由应用程序自己使用;0XC000到0XFFFF范围的消息用来和其他应用程序通信,为了ID的唯一性,使用::RegisterWindowMessage来得到该范围的消息ID。   消息结构和消息处理   消息的结构   为了从消息队列获取消息信息,需要使用MSG结构。例如,::GetMessage函数(从消息队列得到消息并从队列中移走)和::PeekMessage函数(从消息队列得到消息但是可以不移走)都使用了该结构来保存获得的消息信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值