下载本文示例代码
MFC的消息映射机制 MFC的设计者们在设计MFC时,紧紧把握一个目标,那就是尽可能使得MFC的代码要小,速度尽可能快。为了这个目标,他们使用了许多技巧,其中很多技巧体现在宏的运用上,实现MFC的消息映射的机制就是其中之一。 同MFC消息映射机制有关的宏有下面几个: DECLARE_MESSAGE_MAP()宏 BEGIN_MESSAGE_MAP(theClass, baseClass)和END_MESSAGE_MAP()宏 弄懂MFC消息映射机制的最好办法是将找出一个具体的实例,将这些宏展开,并找出相关的数据结构。 DECLARE_MESSAGE_MAP() DECLARE_MESSAGE_MAP()宏的定义如下: #define DECLARE_MESSAGE_MAP() \ private: \ static const AFX_MSGMAP_ENTRY _messageEntries[]; \ protected: \ static AFX_DATA const AFX_MSGMAP messageMap; \ virtual const AFX_MSGMAP* GetMessageMap() const; \从上面的定义可以看出,DECLARE_MESSAGE_MAP()作下面三件事: 定义一个长度不定的静态数组变量_messageEntries[]; 定义一个静态变量messageMap; 定义一个虚拟函数GetMessageMap();在DECLARE_MESSAGE_MAP()宏中,涉及到MFC中两个对外不公开的数据结构AFX_MSGMAP_ENTRY和AFX_MSGMAP。为了弄清楚消息映射,有必要考察一下这两个数据结构的定义。 AFX_MSGMAP_ENTRY的定义 struct AFX_MSGMAP_ENTRY { UINT nMessage; // windows message UINT nCode; // control code or WM_NOTIFY code UINT nID; // control ID (or 0 for windows messages) UINT nLastID; // used for entries specifying a range of control id's UINT nSig; // signature type (action) or pointer to message # AFX_PMSG pfn; // routine to call (or special value) };结构中各项的含义注释已经说明得很清楚了,这里不再多述,从上面的定义你是否看出,AFX_MSGMAP_ENTRY结构实际上定义了消息和处理此消息的动作之间的映射关系。因此静态数组变量_messageEntries[]实际上定义了一张表,表中的每一项指定了相应的对象所要处理的消息和处理此消息的函数的对应关系,因而这张表也称为消息映射表。再看看AFX_MSGMAP的定义。 (2)AFX_MSGMAP的定义 struct AFX_MSGMAP { const AFX_MSGMAP* pBaseMap; const AFX_MSGMAP_ENTRY* lpEntries; };不难看出,AFX_MSGMAP定义了一单向链表,链表中每一项的值是一指向消息映射表的指针(实际上就是_messageEntries的值)。通过这个链表,使得在某个类中调用基类的的消息处理函数很容易,因此,“父类的消息处理函数是子类的缺省消息处理函数”就“顺理成章”了。在后面的“MFC窗口的消息处理”一节中会对此作详细的讲解。 BEGIN_MESSAGE_MAP()和END_MESSAGE_MAP() 它们的定义如下: #define BEGIN_MESSAGE_MAP(theClass, baseClass) \ const AFX_MSGMAP* theClass::GetMessageMap() const \ { return &theClass::messageMap; } \ AFX_COMDAT AFX_DATADEF const AFX_MSGMAP theClass::messageMap = \ { &baseClass::messageMap, &theClass::_messageEntries[0] }; \ AFX_COMDAT const AFX_MSGMAP_ENTRY theClass::_messageEntries[] = \ { \ #define END_MESSAGE_MAP() \ {0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \ }; \对应BEGIN_MESSAGE_MAP()的定义可能不是一下子就看得明白,不过不要紧,举一例子就很清楚了。对于BEGIN_MESSAGE_MAP(CView, CWnd),VC预编译器将其展开成下面的形式: const AFX_MSGMAP* CView::GetMessageMap() const { return &CView::messageMap; } AFX_COMDAT AFX_DATADEF const AFX_MSGMAP CView::messageMap = { &CWnd::messageMap, &CView::_messageEntries[0] }; AFX_COMDAT const AFX_MSGMAP_ENTRY CView::_messageEntries[] = { 至于END_MESSAGE_MAP()则不过定义了一个表示映射表结束的标志项,我想大家对于这种简单的技巧应该是很熟悉的,无需多述。共2页。 1 2 8 :
MFC的消息映射机制 MFC的设计者们在设计MFC时,紧紧把握一个目标,那就是尽可能使得MFC的代码要小,速度尽可能快。为了这个目标,他们使用了许多技巧,其中很多技巧体现在宏的运用上,实现MFC的消息映射的机制就是其中之一。 同MFC消息映射机制有关的宏有下面几个: DECLARE_MESSAGE_MAP()宏 BEGIN_MESSAGE_MAP(theClass, baseClass)和END_MESSAGE_MAP()宏 弄懂MFC消息映射机制的最好办法是将找出一个具体的实例,将这些宏展开,并找出相关的数据结构。 DECLARE_MESSAGE_MAP() DECLARE_MESSAGE_MAP()宏的定义如下: #define DECLARE_MESSAGE_MAP() \ private: \ static const AFX_MSGMAP_ENTRY _messageEntries[]; \ protected: \ static AFX_DATA const AFX_MSGMAP messageMap; \ virtual const AFX_MSGMAP* GetMessageMap() const; \从上面的定义可以看出,DECLARE_MESSAGE_MAP()作下面三件事: 定义一个长度不定的静态数组变量_messageEntries[]; 定义一个静态变量messageMap; 定义一个虚拟函数GetMessageMap();在DECLARE_MESSAGE_MAP()宏中,涉及到MFC中两个对外不公开的数据结构AFX_MSGMAP_ENTRY和AFX_MSGMAP。为了弄清楚消息映射,有必要考察一下这两个数据结构的定义。 AFX_MSGMAP_ENTRY的定义 struct AFX_MSGMAP_ENTRY { UINT nMessage; // windows message UINT nCode; // control code or WM_NOTIFY code UINT nID; // control ID (or 0 for windows messages) UINT nLastID; // used for entries specifying a range of control id's UINT nSig; // signature type (action) or pointer to message # AFX_PMSG pfn; // routine to call (or special value) };结构中各项的含义注释已经说明得很清楚了,这里不再多述,从上面的定义你是否看出,AFX_MSGMAP_ENTRY结构实际上定义了消息和处理此消息的动作之间的映射关系。因此静态数组变量_messageEntries[]实际上定义了一张表,表中的每一项指定了相应的对象所要处理的消息和处理此消息的函数的对应关系,因而这张表也称为消息映射表。再看看AFX_MSGMAP的定义。 (2)AFX_MSGMAP的定义 struct AFX_MSGMAP { const AFX_MSGMAP* pBaseMap; const AFX_MSGMAP_ENTRY* lpEntries; };不难看出,AFX_MSGMAP定义了一单向链表,链表中每一项的值是一指向消息映射表的指针(实际上就是_messageEntries的值)。通过这个链表,使得在某个类中调用基类的的消息处理函数很容易,因此,“父类的消息处理函数是子类的缺省消息处理函数”就“顺理成章”了。在后面的“MFC窗口的消息处理”一节中会对此作详细的讲解。 BEGIN_MESSAGE_MAP()和END_MESSAGE_MAP() 它们的定义如下: #define BEGIN_MESSAGE_MAP(theClass, baseClass) \ const AFX_MSGMAP* theClass::GetMessageMap() const \ { return &theClass::messageMap; } \ AFX_COMDAT AFX_DATADEF const AFX_MSGMAP theClass::messageMap = \ { &baseClass::messageMap, &theClass::_messageEntries[0] }; \ AFX_COMDAT const AFX_MSGMAP_ENTRY theClass::_messageEntries[] = \ { \ #define END_MESSAGE_MAP() \ {0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \ }; \对应BEGIN_MESSAGE_MAP()的定义可能不是一下子就看得明白,不过不要紧,举一例子就很清楚了。对于BEGIN_MESSAGE_MAP(CView, CWnd),VC预编译器将其展开成下面的形式: const AFX_MSGMAP* CView::GetMessageMap() const { return &CView::messageMap; } AFX_COMDAT AFX_DATADEF const AFX_MSGMAP CView::messageMap = { &CWnd::messageMap, &CView::_messageEntries[0] }; AFX_COMDAT const AFX_MSGMAP_ENTRY CView::_messageEntries[] = { 至于END_MESSAGE_MAP()则不过定义了一个表示映射表结束的标志项,我想大家对于这种简单的技巧应该是很熟悉的,无需多述。共2页。 1 2 8 :
下载本文示例代码
进入MFC讲坛的前言(四)进入MFC讲坛的前言(四)进入MFC讲坛的前言(四)进入MFC讲坛的前言(四)进入MFC讲坛的前言(四)进入MFC讲坛的前言(四)进入MFC讲坛的前言(四)进入MFC讲坛的前言(四)进入MFC讲坛的前言(四)进入MFC讲坛的前言(四)进入MFC讲坛的前言(四)进入MFC讲坛的前言(四)进入MFC讲坛的前言(四)进入MFC讲坛的前言(四)进入MFC讲坛的前言(四)