MFC消息映射深入挖掘1

来源:互联网 发布:行知实践园 编辑:程序博客网 时间:2024/06/07 02:51

在MFC中,消息分为三大类:
1、命令消息

常见的就是由菜单或快捷键或工具栏产生的消息,MFC通过菜单项的识别码分辨来自各处的消息。

以下是两个例子:

 

凡是派生于CCmdTarget的类,均有资格接收命令消息。

 

2、标准消息

除命令消息外,任何以WM_开头的消息都是标准消息。

以下示例了一个WM_CREATE消息:

 

凡派生至CWnd的类,均可以接收此类消息。也就是说,CWnd及其子类,可以接收命令消息和标准消息

 

3、控件消息

称为Control Notification,这种消息由控件产生,是为了向其父窗口(通常为对话框)通知某种消息。

以下的例子说明了listbox中的项目被选择时,产生一个LBN_SELCHANGE消息。

  


 下面说说消息映射。消息映射其实一个巨大的网,一种数据结构。作用是决定消息的流动路线。

上面的消息映射,都出现了四个奇怪的宏。

DECLARE_MESSAGE_MAP()

BEGIN_MESSAGE_MAP

ON_COMMAND

END_MESSAGE_MAP

其中ON_COMMAND是命令消息的宏,当然也可以是标准消息或控件消息,以ON_开头定义。

如:ON_WM_CREATE,ON_LBN_SELCHANGE

 

下面我们来层层挖掘.

首先是DECLARE_MESSAGE_MAP宏,这个宏声明了一个MessageMap数据类型

这里看到AFX_MSGMAP,定义如下:

 

  

可以看出,pBaseMap指向基类的MessageMap,这个指针提供了一个走访整个继承链表的方法。而lpEntries指向了AFX_MSGMAP_ENTRY结构体.这个结构便是消息映射的网络的单个节点。

 

这个结构体的定义如下,这个结构体的作用是让消息nMessage对应于函数pfn。

其中pfn的定义为函数的指针

typedef void (AFX_MSG_CALL CCmdTarget::*AFX_PMSG)(void);

 

到此为止,只是声明了一种类型,并没有真正的实例化。

 


 

上面已经定义了一个MessageMap的结构,谨记这个结构

struct AFX_MSGMAP

{

    const AFX_MSGMAP* PBaseMap;

    const AFX_MSGMAP_ENTRY* lpEntries;

}

下面的BEGIN/ON/END就是来实例化这个结构,以组成一个庞大的消息映射网络。

下面是详细定义BEGIN/ON/END

 

  

于是,对于这样的宏

BEGIN_MESSAGE_MAP(CtestView, CRichEditView)
ON_WM_CREATE()
ON_COMMAND(IDM_FILE_READ, &CtestView::OnFileRead)

END_MESSAGE_MAP()

 

其中ON_WM_CREATE被定义为:(afxmsg_.h中)

 

ON_COMMAND被定义为:(afxmsg_.h中)

 

展开后就是

  

简单的文字替换,呵呵,这样就一目了然了。

经过以上的处理,现在为CtestView生成了一个messagemap

CtestView::messagemap

{

       pBaseMap->Cview::messagemap;

       lpEntries-> messageEntries[];

}

 

所有派生自CCmdTarget的类都可以接收消息,也就是说,这些类都有一个DECLARE/BEGIN/END宏组,但请注意,CWinThread没有,即CWinApp是直接跳到CCmdTarget的,定义如下:

BEGIN_MESSAGE_MAP(CWinAppCCmdTarget)

好了,通过这些宏,我们构造了一个庞大的消息映射网络.

 

 

 

下一章讨论,MFC如何利用这个网络进行消息映射,到底是谁把消息放入messagemap中,谁执行消息的比较操作等等等。这些都会在下一章揭晓。