消息处理机制:CCmdTarget 和 消息映射表

来源:互联网 发布:快速排序java 编辑:程序博客网 时间:2024/05/16 13:53

MFC的消息处理机制由两部分组成:CCmdTarget类和消息映射表。

 

  • 窗口消息构成

所有的窗口消息由3部分组成

UINT Msg
WPARAM
wParam
LPARAM
lParam

  •  为神马不用虚函数来处理消息?

因为,虚函数是使用类的虚函数表实现的,每个派生类都会带一个虚函数表的拷贝。虚函数表中的每个入口都是一个4字节指针,这样每个类对象就会在虚函数表中带来大量的额外字节。同时,窗口消息的个数和种类随时会发生变化,在消息改变时,使用虚函数实现的消息机制容易导致代码的废弃

  • 消息机制内幕

MFC的消息映射技术由两部分组成:CCmdTarget类 和 消息映射表。CCmdTarget是所有接受窗口消息和命令对象的基类,为了接受消息,类必须从CCmdTarget派生。消息映射表是将窗口消息与处理消息的类成员函数关联起来的机制。消息映射表数据结构和消息映射宏是消息映射系统的另外的两个重要的方面。

 

  (a) 两个消息映射表数据结构

  AFX_MSGMAP_ENTRY 消息映射项  ( 见afxwin.h )

[cpp] view plaincopy
  1. struct AFX_MSGMAP_ENTRY  
  2. {  
  3.     UINT nMessage;   // windows message  
  4.     UINT nCode;      // 控件代码或WM_NOTIFY代码,MFC 3.0新增  
  5.     UINT nID;        // 产生消息的控件ID(0代表Windows消息)  
  6.     UINT nLastID;    // 用来指定控件ID范围,MFC 3.0新增  
  7.     UINT_PTR nSig;       // signature type (action) or pointer to message #  
  8.     AFX_PMSG pfn;    // 消息处理函数  
  9. };  

 

  AFX_MSGMAP 消息映射表 ( 见afxwin.h )

 

[cpp] view plaincopy
  1. struct AFX_MSGMAP  
  2. {  
  3.     const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)(); // 指向基类映射表项的指针  
  4.     const AFX_MSGMAP_ENTRY* lpEntries;  // 消息映射表  
  5. };  

 

 

  (b) 消息映射宏

MFC提供了三个宏来产生消息映射表:DECLARE_MESSAGE_MAP、BEGIN_MESSAGE_MAP、END_MESSAGE_MAP。要在类中使用消息映射表,最基本的办法是在类声明中包含DECLARE_MESSAGE_MAP (.h文件),在类实现体中包含BEGIN_MESSAGE_MAP、END_MESSAGE_MAP和消息映射信息(.cpp文件)

 

 DECLARE_MESSAGE_MAP  ( 见afxwin.h )

[cpp] view plaincopy
  1. #define DECLARE_MESSAGE_MAP() /  
  2. protected: /  
  3.     static const AFX_MSGMAP* PASCAL GetThisMessageMap(); /  
  4.     virtual const AFX_MSGMAP* GetMessageMap() const; /  

定义了两个Protect函数,GetThisMessageMap用于返回本类中的消息映射表指针,GetMesssageMap是个虚函数

 

BEGIN_MESSAGE_MAP  ( 见afxwin.h )

[cpp] view plaincopy
  1. #define BEGIN_MESSAGE_MAP(theClass, baseClass) /  
  2.     const AFX_MSGMAP* theClass::GetMessageMap() const /  
  3.         { return GetThisMessageMap(); } /  
  4.     const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() /  
  5.     { /  
  6.         typedef theClass ThisClass;                        /  
  7.         typedef baseClass TheBaseClass;                    /  
  8.         static const AFX_MSGMAP_ENTRY _messageEntries[] =  /  
  9.         {  

GetMessageMap 和 GetThisMessageMap函数的实现,在GetThisMessageMap中一个函数中定义了两个函数静态变量:_messageEntries 表示所有的消息映射项、messageMap表示消息映射表(见下)

 

END_MESSAGE_MAP  ( 见afxwin.h )

[cpp] view plaincopy
  1. #define END_MESSAGE_MAP() /  
  2.         {0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } /  
  3.     }; /  
  4.         static const AFX_MSGMAP messageMap = /  
  5.         { &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; /  
  6.         return &messageMap; /  
  7.     }  

 

BEGIN_MESSAGE_MAP 和 END_MESSAGE_MAP之间的内容是一系列消息映射表的入口宏。这些宏扩展后可以填充类的消息映射表_messageEntries。MFC定义的各种消息映射表入口宏,见下表

 

  (3)MFC定义各种消息映射表入口宏

消息类型

宏形式

参数

预定义窗口消息

ON_WM_XXXX

None

命令

ON_COMMAND

Command Id, Handler Name

命令ID的范围

ON_COMMAND_RANGE

Start ID, End ID,

Handler Name

更新命令

ON_UPDATE_COMMAND_UI

Commnad Id, Handler Name

用于更新的命令ID的范围

ON_UPDATE_COMMAND_UI_RANGE

Start ID, End ID,

Handler Name

控件通知

ON_XXXX

Control Id, Handler Name

控件ID范围

ON_CONTROL_RANGE

Notify Code、Start ID、End ID、Handler Name

用户定义的消息

ON_MESSAGE

User-defined Message ID,

Handler Name

注册的窗口消息

ON_REGISTERED_MESSAGE

Registered message ID variable, Handler Name

 

0 0
原创粉丝点击