个人比较看重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;
}