Win32下的消息流程清晰明了,但在MFC下,由于封装的缘故,隐藏的有点深,对一般的开发人员而言,就不甚明了喽。本文试图粗略展示出MFC下消息处理的基本流程。
一、先看一下Win32下的消息处理流程
每一个线程都对应有一个消息队列,利用API函数GetMessage从消息队列中获取消息,然后利用TranslateMessage翻译消息(主要是一些键盘消息),再利用DispatchMessage将消息分发给对应的窗口过程函数处理。
一般我们在WinMain函数中利用如下代码来处理消息:
- while (GetMessage(&msg, NULL, 0, 0))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); }
很显然,整个消息循环很清楚。
二、MFC下的消息处理流程
1、MFC下的消息处理流程由thrdcore.cpp中的AfxInternalPumpMessage开始:
- BOOL AFXAPI AfxInternalPumpMessage()
- {
- MSG msg;
- ::GetMessage(&msg, NULL, NULL, NULL);
- if (!AfxPreTranslateMessage(&msg))
- {
- ::TranslateMessage(&msg);
- ::DispatchMessage(&msg);
- }
- return TRUE;
- }
BOOL AFXAPI AfxInternalPumpMessage() { MSG msg; ::GetMessage(&msg, NULL, NULL, NULL); if (!AfxPreTranslateMessage(&msg)) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); } return TRUE; }
注:以上代码为示意代码,具体请参照MFC的源码。
很显然,其消息处理流程也类似<一>中Win32下的消息处理,只不过在调用TranslateMessage、DispatchMessage处理消息前增加了类似过滤的函数AfxPreTranslateMessage。该函数会调用CWnd类的PreTranslateMessage函数,函数返回True则消息将不会被处理。我们经常会通过重载CWnd类的PreTranslateMessage来改变MFC的消息控制流程。
2、窗口过程函数
通过调用DispatchMessage将消息分发给了具体的窗口过程函数处理。MFC下的所有窗口都拥有公用的窗口过程函数AfxWndProc。该函数的示意代码如下:
- LRESULT CALLBACK AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
- {
- CWnd* pWnd = CWnd::FromHandlePermanent(hWnd); //从HWND获取对应的CWnd*
- if (pWnd == NULL || pWnd->m_hWnd != hWnd)
- return ::DefWindowProc(hWnd, nMsg, wParam, lParam);
- else
- return pWnd->WindowProc(nMsg, wParam, lParam);
- }
LRESULT CALLBACK AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam) { CWnd* pWnd = CWnd::FromHandlePermanent(hWnd); //从HWND获取对应的CWnd* if (pWnd == NULL || pWnd->m_hWnd != hWnd) return ::DefWindowProc(hWnd, nMsg, wParam, lParam); else return pWnd->WindowProc(nMsg, wParam, lParam); }
很显然,调用了CWnd类的虚函数virtual CWnd::WindowProc处理。
- LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
- {
- // OnWndMsg does most of the work, except for DefWindowProc call
- LRESULT lResult = 0;
- if (!OnWndMsg(message, wParam, lParam, &lResult))
- lResult = DefWindowProc(message, wParam, lParam);
- return lResult;
- }
LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam) { // OnWndMsg does most of the work, except for DefWindowProc call LRESULT lResult = 0; if (!OnWndMsg(message, wParam, lParam, &lResult)) lResult = DefWindowProc(message, wParam, lParam); return lResult; }
WindowProc函数又调用了CWnd类的虚函数virtual CWnd::OnWndMsg处理。
- BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)
- {
- LRESULT lResult = 0;
- union MessageMapFunctions mmf;
- mmf.pfn = 0;
- CInternalGlobalLock winMsgLock;
- // special case for commands
- if (message == WM_COMMAND)
- {
- if (OnCommand(wParam, lParam))
- {
- lResult = 1;
- goto LReturnTrue;
- }
- return FALSE;
- }
- // special case for notifies
- if (message == WM_NOTIFY)
- {
- NMHDR* pNMHDR = (NMHDR*)lParam;
- if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult))
- goto LReturnTrue;
- return FALSE;
- }
- ......
- return TRUE;
- }
BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult) { LRESULT lResult = 0; union MessageMapFunctions mmf; mmf.pfn = 0; CInternalGlobalLock winMsgLock; // special case for commands if (message == WM_COMMAND) { if (OnCommand(wParam, lParam)) { lResult = 1; goto LReturnTrue; } return FALSE; } // special case for notifies if (message == WM_NOTIFY) { NMHDR* pNMHDR = (NMHDR*)lParam; if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult)) goto LReturnTrue; return FALSE; } ...... return TRUE; }
在OnWndMsg函数中会根据具体的消息类型,在MFC的消息映射表中找到对应的函数处理。
以上就是MFC处理消息的大致流程。
from:http://blog.csdn.net/wangyao1052/article/details/8045017
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!