MFC消息处理流程概述 .

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

 

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

 

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

 

 

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

 

[cpp] view plaincopyprint?

  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开始:

 

[cpp] view plaincopyprint?

  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。该函数的示意代码如下:

 

[cpp] view plaincopyprint?

  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处理。

[cpp] view plaincopyprint?

  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处理。

 

 

[cpp] view plaincopyprint?

  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
时间: 2024-10-01 15:24:18

MFC消息处理流程概述 .的相关文章

《Adobe Premiere Pro CC完全剖析》——工作流程概述

工作流程概述 后期制作的过程反映在Adobe Premire Pro的功能及Adobe Creative Cloud所有视频软件的工作方式上.有了这么多可支配的软件,你的工作流程将会非常顺畅. 因此,让我们结合前后期制作的实际过程,探索Adobe Premiere Pro单独使用及与套件内其他软件协同工作时的选项.整体情况 这里有一点很重要,手头有这么多的软件可供使用,对于选择什么样的软件让使用和学习更顺畅,应作出最佳选择. 表1.1是Adobe Premiere Pro内部可完成功能(几乎所有

MFC 消息处理顺序

MFC 消息传递顺序 LRESULT CALLBACK AfxWndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)   {       // special message which identifies the window as using AfxWndProc       if (nMsg == WM_QUERYAFXWNDPROC)           return 1;        // all other mess

MFC线程处理概述

      事实上,Win32 API提供了_beginthreadex函数,可以让用户在底层启动线程.总地来说,Win32 API提供的线程处理的接口,引用较为复杂.因此,在Win32 API的基础上,MFC提供了处理线程的类和函数.其中,MFC提供处理线程的类为CWinThread类.CWinThread类使用线程本地存储来管理在MFC环境中的线程的上下文信息.一般地说,用户可以直接声明CWinThread对象,但在许多情况下,可以让MFC的全局函数AfxBeginThread来创建CWin

WebKit加载流程 - 概述

之前写了几篇加载流程的说明,是从下向上看,有点只见树木不见森林的感觉.经过最近一段时间的学习,有了能加以概括抽象的方法. WebKit加载流程和页面组成是直接相关的,页面就是WebKit要加载的对象.所以WebKit负责加载的类也与负责页面管理的类相对应.Apple关于WebView的说明里清楚表现了页面视图上的MVC结构: 一个页面从元素上也有其层次结构,并且和加载类对应,如下: 从页面元素上讲WebView代表了一个页面的呈现,对应一个Page. 一个Page包含一个或多个Frame,其中一

Android Framework Boot Up Overview(Android系统框架启动流程概述)

目录章节: 1.Framework运行环境 2.zygote的启动 3.SystemServer进程的启动4.启动第一个Activity 概述图: 由于将PPT格式转换为博客内容相当花费时间,请对详细介绍内容感兴趣的同学直接下载文档: AndroidFrameworkBootUpOverview 参考: Android内核剖析-柯元旦(推荐)

网站项目建设流程概述

项目  一.概念 网站项目管理就是根据特定的规范.在预算范围内.按时完成的网站开发任务. 二.需求分析 项目立项 我们接到客户的业务咨询,经过双方不断的接洽和了解,并通过基本的可行性讨论够,初步达成制作协议,这时就需要将项目立项.较好的做法是成立一个专门的项目小组,小组成员包括:项目经理,网页设计,程序员,测试员,编辑/文档等必须人员.项目实行项目经理制. 客户的需求说明书 第一步是需要客户提供一个完整的需求说明.很多客户对自己的需求并不是很清楚,需要您不断引导和帮助分析.曾经有一次,我问客户:

Android个层次调用流程概述

Android的硬件抽象层:         简单来说,就是对Linux内核驱动程序的封装,向上提供接口,屏蔽低层的实现细节.         也就是说,把对硬件的支持分成了两层,                一层放在用户空间(User Space),(硬件抽象层)                一层放在内核空间(Kernel Space),(Linux内核驱动程序)   下面这个图阐述了硬件抽象层在Android系统中的位置,以及它和其它层的关系: 二,简单的总结 进入到Android源代码

live555 RTSP服务器建立及消息处理流程

DynamicRTSPServer::creatnew():    1.调用继承自RTPSever::setUpOurSocket:        1.调用 GroupsockHelper 的 setupStreamSocket创建一个socket连接,并绑定,        2.设置socket的发送缓存大小,        3.调用listen开始监听端口,设置同时最大能处理连接数 LISTEN_BACKLOG_SIZE=20,如果达到这个上限则client端将收到ECONNERREFUSE

网站项目建设流程概述详细分析_应用技巧

一.概念  网站项目管理就是根据特定的规范.在预算范围内.按时完成的网站开发任务.  二.需求分析  项目立项   我们接到客户的业务咨询,经过双方不断的接洽和了解,并通过基本的可行性讨论够,初步达成制作协议,这时就需要将项目立项.较好的做法是成立一个专门的项目小组,小组成员包括:项目经理,网页设计,程序员,测试员,编辑/文档等必须人员.项目实行项目经理制.   客户的需求说明书   第一步是需要客户提供一个完整的需求说明.很多客户对自己的需求并不是很清楚,需要您不断引导和帮助分析.曾经有一次,