MFC消息处理流程概述 .

简介: Win32下的消息流程清晰明了,但在MFC下,由于封装的缘故,隐藏的有点深,对一般的开发人员而言,就不甚明了喽。本文试图粗略展示出MFC下消息处理的基本流程。   一、先看一下Win32下的消息处理流程   每一个线程都对应有一个消息队列,利用API函数GetMessage从消息队列中获取消息,然后利用TranslateMessage翻译消息(主要是一些键盘消息),再利用DispatchMessage将消息分发给对应的窗口过程函数处理。

Win32下的消息流程清晰明了,但在MFC下,由于封装的缘故,隐藏的有点深,对一般的开发人员而言,就不甚明了喽。本文试图粗略展示出MFC下消息处理的基本流程。

 

一、先看一下Win32下的消息处理流程

 

    每一个线程都对应有一个消息队列,利用API函数GetMessage从消息队列中获取消息,然后利用TranslateMessage翻译消息(主要是一些键盘消息),再利用DispatchMessage将消息分发给对应的窗口过程函数处理。

 

 

    一般我们在WinMain函数中利用如下代码来处理消息:

 

  1. while (GetMessage(&msg, NULL, 0, 0))  
  2. {  
  3.     TranslateMessage(&msg);  
  4.     DispatchMessage(&msg);  
  5. }  
while (GetMessage(&msg, NULL, 0, 0))
{
    TranslateMessage(&msg);
    DispatchMessage(&msg);
}

 

 

    很显然,整个消息循环很清楚。

 

二、MFC下的消息处理流程

 

1、MFC下的消息处理流程由thrdcore.cpp中的AfxInternalPumpMessage开始:

 

  1. BOOL AFXAPI AfxInternalPumpMessage()  
  2. {  
  3.     MSG msg;  
  4.     ::GetMessage(&msg, NULL, NULL, NULL);  
  5.     if (!AfxPreTranslateMessage(&msg))  
  6.     {  
  7.         ::TranslateMessage(&msg);  
  8.  ::DispatchMessage(&msg);  
  9.     }  
  10.     return TRUE;  
  11. }  
    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。该函数的示意代码如下:

 

  1. LRESULT CALLBACK AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)  
  2. {  
  3.         CWnd* pWnd = CWnd::FromHandlePermanent(hWnd);  //从HWND获取对应的CWnd*   
  4.         if (pWnd == NULL || pWnd->m_hWnd != hWnd)  
  5.                 return ::DefWindowProc(hWnd, nMsg, wParam, lParam);  
  6.         else      
  7.                 return pWnd->WindowProc(nMsg, wParam, lParam);  
  8. }  
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处理。

  1. LRESULT CWnd::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)  
  2. {  
  3.     // OnWndMsg does most of the work, except for DefWindowProc call   
  4.     LRESULT lResult = 0;  
  5.     if (!OnWndMsg(message, wParam, lParam, &lResult))  
  6.         lResult = DefWindowProc(message, wParam, lParam);  
  7.     return lResult;  
  8. }  
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处理。

 

 

  1. BOOL CWnd::OnWndMsg(UINT message, WPARAM wParam, LPARAM lParam, LRESULT* pResult)  
  2. {  
  3.     LRESULT lResult = 0;  
  4.     union MessageMapFunctions mmf;  
  5.     mmf.pfn = 0;  
  6.     CInternalGlobalLock winMsgLock;  
  7.     // special case for commands   
  8.     if (message == WM_COMMAND)  
  9.     {  
  10.         if (OnCommand(wParam, lParam))  
  11.         {  
  12.             lResult = 1;  
  13.             goto LReturnTrue;  
  14.         }  
  15.         return FALSE;  
  16.     }  
  17.   
  18.     // special case for notifies   
  19.     if (message == WM_NOTIFY)  
  20.     {  
  21.         NMHDR* pNMHDR = (NMHDR*)lParam;  
  22.         if (pNMHDR->hwndFrom != NULL && OnNotify(wParam, lParam, &lResult))  
  23.             goto LReturnTrue;  
  24.         return FALSE;  
  25.     }  
  26.       
  27.     ......  
  28.   
  29.     return TRUE;  
  30. }  
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
目录
相关文章
|
11月前
|
算法 调度 数据安全/隐私保护
Docker Swarm 中Manager(管理节点)
【10月更文挑战第9天】
255 2
|
编解码 算法 计算机视觉
【MATLAB】 小波分解信号分解+FFT傅里叶频谱变换组合算法
【MATLAB】 小波分解信号分解+FFT傅里叶频谱变换组合算法
516 0
|
11月前
|
缓存 算法 关系型数据库
Mysql(3)—数据库相关概念及工作原理
数据库是一个以某种有组织的方式存储的数据集合。它通常包括一个或多个不同的主题领域或用途的数据表。
406 5
Mysql(3)—数据库相关概念及工作原理
|
3月前
|
前端开发 Java 微服务
2025 版 Java 学习路线图之技术方案与实操指南详解
这是一份详尽的Java学习路线图,涵盖从入门到精通的全流程。基础阶段包括环境搭建、语法基础与面向对象编程;进阶阶段深入数据结构、算法、多线程及JVM原理;框架阶段学习Spring、MyBatis等工具;数据库阶段掌握SQL与NoSQL技术;前端阶段了解HTML、CSS及JavaScript框架;分布式与微服务阶段探讨容器化、服务注册与发现;最后通过项目实战提升性能优化与代码规范能力。资源地址:[https://pan.quark.cn/s/14fcf913bae6](https://pan.quark.cn/s/14fcf913bae6)。
250 7
|
6月前
|
Windows
电脑网络图标消失了怎么办?3步教你找回,简单快捷!
当电脑网络图标消失,宽带和WiFi图标变成一个球时,可通过以下步骤解决:1. 使用快捷键`Win+R`输入`services.msc`进入服务管理器;2. 找到并启动Wired AutoConfig、WLAN AutoConfig和WLAN Direct服务,设置启动类型为自动;3. 重启电脑验证问题是否解决。此方法可恢复网络功能。
611 0
|
机器学习/深度学习 人工智能 算法
基于机械臂的工业分拣系统
【8月更文挑战第2天】基于机械臂的工业分拣系统。
275 3
|
负载均衡 监控 网络协议
玩核心交换机,必须掌握的6个知识点!
玩核心交换机,必须掌握的6个知识点!
460 1
|
监控 数据可视化 搜索推荐
ERP系统中的财务预测与预算编制解析
【7月更文挑战第25天】 ERP系统中的财务预测与预算编制解析
491 0
|
人工智能 自然语言处理 IDE
通义灵码_智能编码助手_AI编程——程序员必备编程利器!
*通义灵码是阿里云的AI编程助手,提供代码智能生成、研发问答等功能,如实时续写、自然语言转代码、单元测试、优化、注释生成等。支持多种编程语言,IDE包括JetBrains、VS Code和VS 2022。优势包括跨文件感知、阿里云服务优化、多IDE集成、研发问答和双模引擎。个人基础版免费,专业版现限时免费,企业版有不同的定价和服务。
1466 0
|
存储 Linux Shell
【Shell 命令集合 磁盘维护 】Linux 关闭Linux系统中的交换空间 swapoff命令使用教程
【Shell 命令集合 磁盘维护 】Linux 关闭Linux系统中的交换空间 swapoff命令使用教程
346 1