MFC技术系列(二)--窗口消息(4)

本文详细介绍了MFC中的消息分发,包括WM_COMMAND消息的处理,WM_NOTIFY消息,直接分发的消息,ON_UPDATE_COMMAND_UI宏的作用,PreTranslateMessage的预处理以及消息映射表的工作原理。通过对消息分发流程的分析,揭示了MFC如何处理命令消息和窗口消息,以及如何实现命令路由和菜单状态更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

接上篇, 窗口消息(3)

5. MFC中的消息分发

消息的Hook:标准的消息循环被MFC封装在AfxPumpMessage方法中。消息一旦被Dispatch,那么接下来如何进入到窗口的WndProc方法中呢?MFC在窗口创建时,使用AfxHookWindowCreate方法(使用SetWindowsHookEx API方法+WH_CBT参数),使得消息能够输出到一个全局方法AfxWndProcBase中(如果是静态链接到MFC,则为AfxWndProc)。以此为出发点,MFC通过消息的窗口句柄获得对应的窗口对象,然后调用其WndProc方法(在AfxCallWndProc中)。

在消息被分发前,有两点值得注意:

1.       WM_KICKIDLE消息不会被分发。该消息为MFC私有消息。其处理方式请参见《对话框》一文。

2.       AfxPreTranslateMessage先被调用。如果返回TRUE,那么消息将不会被进一步处理(分发)

 

MFC中,根据分发机制的不同,可将消息分为两类,一类为命令消息,即:WM_COMMAND消息,包括:菜单响应消息,一些基础控件的通知消息(例如:BN_CLICKEDEN_UPDATE等)。它的分发路径为由顶向下,即:从应用主窗口向下传递。另一类为直接分发到窗口的消息,包括:鼠标消息、键盘消息。

通知消息还有一种形式,即:WM_NOTIFY消息。

实际上,从消息的角度来看,消息都是直接到窗口的。只有在MFC的框架下,才引申出消息分发和路由的概念。对于所谓的命令消息的传递,是由命令消息的接收窗口发起的,结合MFC的各种消息映射宏,能够方便地处理消息,最直接地就是避免了消息参数格式的转换,另外,消息可以灵活地被路由。

1.1           WM_COMMAND消息

下面的场景是在一个对话框上点击一个按钮后,程序调用堆栈的情况:

1Dialog1.exe!CDialog1Dlg::OnBnClickedButton1()  Line 157       C++

2mfc71d.dll!_AfxDispatchCmdMsg(CCmdTarget * pTarget=0x0012fe38, unsigned int nID=1000, int nCode=0, void (void)* pfn=0x004114dd, void * pExtra=0x00000000, unsigned int nSig=53, AFX_CMDHANDLERINFO * pHandlerInfo=0x00000000)  Line 89     C++

3.mfc71d.dll!CCmdTarget::OnCmdMsg(unsigned int nID=1000, int nCode=0, void * pExtra=0x00000000, AFX_CMDHANDLERINFO * pHandlerInfo=0x00000000)  Line 396 + 0x27        C++

4.mfc71d.dll!CDialog::OnCmdMsg(unsigned int nID=1000, int nCode=0, void * pExtra=0x00000000, AFX_CMDHANDLERINFO * pHandlerInfo=0x00000000)  Line 88 + 0x18 C++

5.mfc71d.dll!CWnd::OnCommand(unsigned int wParam=1000, long lParam=264964)  Line 2550         C++

6.mfc71d.dll!CWnd::OnWndMsg(unsigned int message=273, unsigned int wParam=1000, long lParam=264964, long * pResult=0x0012f81c)  Line 1759 + 0x1c        C++

7.mfc71d.dll!CWnd::WindowProc(unsigned int message=273, unsigned int wParam=1000, long lParam=264964)  Line 1745 + 0x1e         C++

8.mfc71d.dll!AfxCallWndProc(CWnd * pWnd=0x0012fe38, HWND__ * hWnd=0x00030aba, unsigned int nMsg=273, unsigned int wParam=1000, long lParam=264964)  Line 241 + 0x1a       C++

9.mfc71d.dll!AfxWndProc(HWND__ * hWnd=0x00030aba, unsigned int nMsg=273, unsigned int wParam=1000, long lParam=264964)  Line 389         C++

10.mfc71d.dll!AfxWndProcBase(HWND__ * hWnd=0x00030aba, unsigned int nMsg=273, unsigned int wParam=1000, long lParam=264964)  Line 209 + 0x15       C++

上述内容中,除了前面已经提到的几个MFC中所有消息的入口及相关方法外,已经用红色标出了消息链条上更进一步的重要的方法,这些方法也是命令消息传递最基本的路线。其中,

CWnd::WndProc:对话框没有重载WndProc

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值