个人比较看重MFC的消息映射机制,因为一直有项目的原因没有时间进行深入的理解一下消息映射机制,今天就正好上班空闲便单刀直入打开《深入浅出MFC》(想要学MFC这本书还是很不错的开始)电子书直接翻到这一部分,想着今天一定要懂,就这样,懂了!
MFC消息映射的核心思想是建立一个映射表,表中包含三类信息,消息的基本信息,消息的处理函数以及基类对该消息的处理
在消息产生时程序会先找映射表中当前定义的消息处理函数,如果没有就会去调基类的消息处理函数。
1MFC中的消息映射主要涉及两个结构体的操作AFX_MSGMAP和AFX_MSGMAP_ENTRY。
AFX_MSGMAP相当于一个映射表,用来保存基类和当前类的消息处理信息
struct AFX_MSGMAP
{
const AFX_MSGMAP* (*pfnGetBaseMap)();// 基类的该消息的处理
const AFX_MSGMAP_ENTRY*lpEntries; //消息的基本信息、消息的处理函数
};
如图所示
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_PTR nSig; // signature type (action) or pointer tomessage #
AFX_PMSGpfn; // typedef void (AFX_MSG_CALLCCmdTarget::*AFX_PMSG)(void);
};
2 在头文件中加DECLARE_MESSAGE_MAP的宏相当于声明了两个成员函数,主要作用是构建以一个映射表(数据结构),表中包括消息的基本信息、消息的处理函数和基类的该消息的处理函数
static const AFX_MSGMAP* PASCAL GetThisMessageMap(); virtual const AFX_MSGMAP* GetMessageMap() const;
3 BEGIN_MESSAGE_MAP(theClass,baseClass)和END_MESSAGE_MAP()相当于头文件中成员函数的实现源码大体如下
BEGIN_MESSAGE_MAP是实现成员函数的主要部分
#define BEGIN_MESSAGE_MAP(theClass, baseClass) \ const AFX_MSGMAP* theClass::GetMessageMap() const\ { returnGetThisMessageMap(); } \ const AFX_MSGMAP* PASCALtheClass::GetThisMessageMap()\ { \ typedeftheClass ThisClass; \ typedefbaseClass TheBaseClass; \ staticconst AFX_MSGMAP_ENTRY_messageEntries[] = \ { //END_MESSAGE_MAP相当于给映射表加了一个结束项 #define END_MESSAGE_MAP()\ {0, 0,0, 0, AfxSig_end, (AFX_PMSG)0} \ }; \ static const AFX_MSGMAP messageMap = \ {&TheBaseClass::GetThisMessageMap,&_messageEntries[0] }; \ return &messageMap; \ } //AfxSig_end标志消息映射的结束
4 基类对于GetThisMessageMap的定义
CCmdTarget
const AFX_MSGMAP* CCmdTarget::GetThisMessageMap() { static const AFX_MSGMAP_ENTRY_messageEntries[] = { { 0, 0, AfxSig_end, 0 } // nothing here }; static const AFX_MSGMAP messageMap = { NULL, //没有父类的消息处理函数 &_messageEntries[0] //此时没有消息 }; return &messageMap; }