本专栏上两篇文章分别介绍了【MFC】05.MFC第一大机制:程序启动机制和【MFC】06.MFC第二大机制:窗口创建机制,这篇文章来为大家介绍MFC的第三大机制:消息映射
-
typfd要实现消息映射,必须满足的三个条件:
类必须继承于CmdTargert
类必须声明重定义 DECLARE_MESSAGE_MAP
类外必须实现DEGIN_MESSINGE_MAP()
END_MESSAGE_MAP()
自己的窗口类{ LERESULT onCreate(WPARAM wParam,LPARAM lParam){ AfxMessageBox("WM_CREATE"); } //定义宏: DECLARE_MESSAGE_MAP() } //类外实现消息映射: BEGIN_MESSAGE_MAP(cMyFrameWnd,CFrameWnd) ON_MESSAGE(WM_CREATE,onCreate); END_MESSAGE_MAP()
-
在Win32程序中封装消息:
我们定义一张映射表,当进入WndProc的时候,通过查找这张表的映射关系,来执行对应的函数:
typedef struct MESSAGE_ENTRY{ int message; int (*pFun)(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam); } struct MESSAGE_ENTRY MessageMap[]{ 映射容器: WM_PAINT,函数地址 }
MFC的消息映射机制:
- 宏展开:
DECLARE_MESSAGE_MAP(){ //静态函数 static const AFX_MSGMAP* PASCAL GetThisMessageMap(); //虚函数 virtual const AFX_MSGMAP* GetMessageMap() const; } 实现宏展开: DECLARE_MESSAGE_MAP(){ //静态函数 static const AFX_MSGMAP* PASCAL GetThisMessageMap(); //虚函数 virtual const AFX_MSGMAP* GetMessageMap() const; } BEGIN_MESSAGE_MAP(CMFCApplication1App, CWinApp){ //这里是实现虚函数, 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[] = { {0, 0, 0, 0, AfxSig_end, (AFX_PMSG)0 } }; static const AFX_MSGMAP messageMap = { &TheBaseClass::GetThisMessageMap,//我们的弗雷德静态函数地址 &_messageEntries[0] };//本类消息结构体的数组首地址 return &messageMap; } }
我们来看看struct AFXmMSGMAP_ENTRY结构体:
struct AFX_MSGMAP_ENTRY
{
UINT nMessage; //消息ID
UINT nCode; //win32通知码
UINT nID; //命令ID WM_COMMAND 菜单 按钮 快捷键 加速键 1000
UINT nLastID; //最后ID 1004
UINT_PTR nSig; //处理消息的类型
AFX_PMSG pfn; //我们的处理消息的函数地址
};
消息回调:
LRESULT CALLBACK AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{
CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);
AfxCallWndProc(pWnd, hWnd, nMsg, wParam, lParam);
{
pWnd->WindowProc(nMsg, wParam, lParam)
{
OnWndMsg(message, wParam, lParam, &lResult)
{
//函数签名 里面有函数指针
union MessageMapFunctions mmf;
//返回链表头节点
const AFX_MSGMAP* pMessageMap; pMessageMap = this->GetMessageMap();
const AFX_MSGMAP_ENTRY* lpEntry;
for (/* pMessageMap already init'ed */;
pMessageMap->pfnGetBaseMap != NULL; //判断节点等不等于空
pMessageMap = (*pMessageMap->pfnGetBaseMap)()//找下一个节点
)
{
lpEntry = AfxFindMessageEntry(pMessageMap->lpEntries,message, 0, 0)) != NULL)
//消息函数的地址
mmf.pfn = lpEntry->pfn;
switch (lpEntry->nSig)
{
lResult = (this->*mmf.pfn_l_w_l)(wParam, lParam);
}
}
}
}
}
}