DECLARE_MESSAGE_MAP()是MFC定义的一个宏,在里面定义了两个函数:GetMessageMap()和GetThisMessageMap()
BEGIN_MESSAGE_MAP(thisClass,baseClass)的作用是,此时去定义GetMessageMap(),他返回GetThisMessageMap()。在GetThisMessageMap()里面,定义了一个数组,类型为_AFX_MSG,中间的ON_MESSAGE()实质上是在给结构体数组初始化
DECLARE_MESSAGE_MAP宏
在 MFC 几乎每个头文件下(类的最后一行声明),都会有这么几行代码:
// 生成的消息映射函数
protected:
DECLARE_MESSAGE_MAP()
我们看一看 DECLARE_MESSAGE_MAP到底为何物,查看 DECLARE_MESSAGE_MAP源码(c:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\include\afxwin.h):
#define DECLARE_MESSAGE_MAP() \
protected: \
static const AFX_MSGMAP* PASCAL GetThisMessageMap(); \
virtual const AFX_MSGMAP* GetMessageMap() const; \
我们看到了一个陌生的类型 AFX_MSGMAP ,查看其定义:
struct AFX_MSGMAP
{
const AFX_MSGMAP* (PASCAL* pfnGetBaseMap)();
const AFX_MSGMAP_ENTRY* lpEntries;
};
这个结构体第一个成员是一个函数指针,第二个成员类型为 AFX_MSGMAP_ENTRY* ,查看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 to message #
AFX_PMSG pfn; // routine to call (or special value)
};
AFX_MSGMAP_ENTRY 定义一些消息的相关信息,AFX_PSG 定义为:
typedef void (AFX_MSG_CALL CCmdTarget::*AFX_PMSG)(void);
是一个函数指针。是不是将每个消息与其处理方法绑定起来呢?真有可能。
BEGIN_MESSAGE_MAP/ON.../END_MESSAGEBOX 宏
在MFC 几乎每个(类定义的)源文件下都会出现下面几行代码(或者类似):
BEGIN_MESSAGE_MAP(CXXX, C***)
ON_……
END_MESSAGE_MAP()
我们继续一探究竟,查看这几个宏的源码:
#define BEGIN_MESSAGE_MAP(theClass, baseClass) \
PTM_WARNING_DISABLE \
const AFX_MSGMAP* theClass::GetMessageMap() const \
{ return GetThisMessageMap(); } \
const AFX_MSGMAP* PASCAL theClass::GetThisMessageMap() \
{ \
typedef theClass ThisClass; \
typedef baseClass TheBaseClass; \
static const AFX_MSGMAP_ENTRY _messageEntries[] = \
{
#define END_MESSAGE_MAP() \
{0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } \
}; \
static const AFX_MSGMAP messageMap = \
{ &TheBaseClass::GetThisMessageMap, &_messageEntries[0] }; \
return &messageMap; \
} \
关于 ON_...类型的宏就多了,下面我摘了(C:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\include\afxmsg_.h)下面一些我们很熟悉的代码:
#define ON_COMMAND(id, memberFxn) \
{ WM_COMMAND, CN_COMMAND, (WORD)id, (WORD)id, AfxSigCmd_v, \
static_cast<AFX_PMSG> (memberFxn) },
// ON_COMMAND(id, OnBar) is the same as
// ON_CONTROL(0, id, OnBar) or ON_BN_CLICKED(0, id, OnBar)
#define ON_NOTIFY(wNotifyCode, id, memberFxn) \
{ WM_NOTIFY, (WORD)(int)wNotifyCode, (WORD)id, (WORD)id, AfxSigNotify_v, \
(AFX_PMSG) \
(static_cast< void (AFX_MSG_CALL CCmdTarget::*)(NMHDR*, LRESULT*) > \
(memberFxn)) },
把几个宏分散开来,没有整体效果。还是举个例子吧:
DECLARE_MESSAGE_MAP()
EGIN_MESSAGE_MAP(CFirstMFCDemoApp, CWinApp)
ON_COMMAND(ID_FILE_NEW, &CWinApp::OnFileNew)
ON_COMMAND(ID_FILE_OPEN, &CWinApp::OnFileOpen)
END_MESSAGE_MAP()
展开以后为:
protected:
static const AFX_MSGMAP* PASCAL GetThisMessageMap();
virtual const AFX_MSGMAP* GetMessageMap() const;
const AFX_MSGMAP* CFirstMFCDemoApp::GetMessageMap() const
{
return GetThisMessageMap();
}
const AFX_MSGMAP* PASCAL
CFirstMFCDemoApp::GetThisMessageMap()
{
typedef CFirstMFCDemoApp ThisClass;
typedef CWinApp TheBaseClass;
static const AFX_MSGMAP_ENTRY _messageEntries[] =
{
{
WM_COMMAND, CN_COMMAND, (WORD)ID_FILE_NEW,
(WORD)ID_FILE_NEW, AfxSigCmd_v,
static_cast<AFX_PMSG> (&CWinApp::OnFileNew)
},
{
WM_COMMAND, CN_COMMAND, (WORD)ID_FILE_OPEN,
(WORD)ID_FILE_OPEN, AfxSigCmd_v,
static_cast<AFX_PMSG> (&CWinApp::OnFileOpen)
},
{
0, 0, 0, 0,
AfxSig_end, (AFX_PMSG)0
}
};
static const AFX_MSGMAP messageMap =
{ &TheBaseClass::GetThisMessageMap,
&_messageEntries[0] };
return &messageMap;
}