MFC的消息循环(::GetMessage,::PeekMessage)消息泵(CWinThread::PumpMessage)和MFC的消息在窗口之间的路由是两件不同的事情 分两个步骤完成: 1 “消息派送”:非对话框程序(MFC Doc/View架构)和对话框程序略有不同,但原理相差不大。但除了少数的消息例如WM_QUIT,所有消息的派送流程基本一致。2 “消息路由”:其中消息分有3种类型,各类型的路由过程不一样。非对话框程序和对话框程序的处理相同。 消息派送消息派送过程如下图 注意:方框代表类函数,圆圈代表执行函数的对象实体。类函数和执行函数的对象一定要分清楚。  程序启动后,构造全局变量tApp,并调用_tWinMain ->AfxWinMain ->AfxWinInit ->CWinThread::InitApplication ->CWinThread::InitInstance ->CWinThread::Run最终进入tApp对象的 CWinThread::Run 函数中。其中右框图中所有操作都是tApp对象完成的。  CWinThread的Run函数里面,调用了PumpMessage函数。PumpMessage是关键函数,它做了两件事情:调用PreTranslateMessage。MFC的消息预处理机制。 调用DispatchMessage做消息分发。 其中PreTranslateMessage函数的作用是:让每个消息的目标窗口(包括他的父窗口,注意不是父类)都有机会参与消息到来之前的处理。下文有具体该函数的内部处理。 DispatchMessage则调用AfxWndProc ,AfxWndProc 调用AfxCallWndProc ,而AfxCallWndProc 则做了关键的一步骤,调用 pWnd->WindowProc(nMsg, wParam, lParam);其中 pWnd为目标窗口对象。完成消息派送,消息成功派送到目标窗口对象的WindowProc函数中。 而后的事情,就是“目标窗口对象”收到消息后,进行消息路由和映射,找到改消息的处理函数。  再看看PreTranslate的内部处理:tApp对象的PreTranslateMessage操作有3种走向:如果(pMsg->hwnd == NULL),说明这是一个线程消息。调用CWinThread::DispatchThreadMessageEx到消息映射表找到消息入口,然后调用消息处理函数。

NOTE: 一般用PostThreadMessage函数发送线程之间的消息,他和窗口消息不同,需要指定线程id,消息被系统放入到目标线程的消息队列中;用ON_THREAD_MESSAGE( message, memberFxn )宏可以映射线程消息和他的处理函数。这个宏必须在应用程序类(从CWinThread继承)中,因为只有应用程序类才处理线程消息。

消息的目标窗口的PreTranslateMessage函数首先得到消息处理权,如果函数返回FALSE,那么他的父窗口将得到消息的处理权,直到主窗口;如果函数返回TRUE(表示消息已经被处理了),那么就不需要调用父类的PreTranslateMessage函数。这样,保证了消息的目标窗口以及他的父窗口都可以有机会调用PreTranslateMessage--在消息发送到窗口之前进行预处理   如果消息的目标窗口和主窗口没有父子关系,那么再调用主窗口的PreTranslateMessage函数。例如非模式对话框

消息路由/映射

到现在消息已经被目标窗口得到了。

主要分2种情况去找处理函数:WM_COMMAND,WM_NOTIFY处理类似

NOTE:MFC 把消息分为三大类:

命令消息(WM_COMMAND):凡由UI 对象产生的消息都是这种命令消息,可能来自菜单或加速键或工具栏。SDK程序主要靠消息的wParam 辨识之,MFC 程序则主要靠菜单项目的识别码(menu ID)辨识之-- 两者其实是相同的。
凡衍生自CCmdTarget 的类别,皆有资格接收改类型消息。几乎构造应用程序的最重要的几个类别都衍生自CCmdTarget。标准消息- 除WM_COMMAND 之外,任何以WM_ 开头的都算是这一类。任何
衍生自CWnd 之类别,均可接收此消息。Control Notification - 这种消息由控制组件产生,为的是向其父窗口通知某种情况。例如当你在ListBox 上选择其中一个项目,ListBox 就
会产生LBN_SELCHANGE 传送给父窗口。这类消息也是以WM_COMMAND 形
式呈现。

“标准消息”处理最直观,直接调用AfxFindMessageEntry函数去“消息映射表”中寻找对应的处理函数。遍历顺序是沿着父类一直上溯。其中消息映射表是MFC代码类似于DECLARE_MESSAGE_MAP()等的宏搭建起来的网。

按照MFC的规定。WM_COMMAND消息就不同了,消息经过了一个由MFC指定的路线。

路线图如下所示:

就是在OnCmdMsg(nID, nCode, pExtra, pHandlerInfo)实现了这个路线。

至此。消息处理全部完成。全图如下:

其他备注:

只要线程有界面元素或者调用GetMessage,或者有线程消息发送过来,系统就会为线程创建一个消息队列。窗口属于创建他的线程。用SendMessage等发送消息到指定窗口,则把该消息放到窗口所在的消息队列。或者可以直接用PostThreadMessage给指定id线程发送消息。 ::PeekMessage(&msg,NULL,0,0,PM_NOREMOVE)的最后一个参数指定检查消息后,把不把消息移出消息队列。 关注OnIdle函数:在CThreadWnd发现消息队列中并没有消息的时候,则调用该函数。用户可重载该函数。在这个处理中将更新UI界面(比如工具栏按钮的enable和disable状态),删除临时对象(比如用FromHandle得到的对象指针。由于这个原因,在函数之间传递由FromHandle得到的对象指针是不安全的,因为他没有持久性)

MFC的消息机制的更多相关文章

  1. <MFC_1>深入剖析MFC的WinMain和消息机制

    一.开篇引论 熟悉Win32开发的朋友,应该非常了解它的基本组成和流程 1. WinMain:书写窗口类(WNDCLASS) -> 注册窗口类 -> 创建窗口 -> 显示窗口和更新窗 ...

  2. MFC学习-第4课 消息机制和MFC作图

    转自: 1.http://blog.sina.com.cn/s/blog_6b5180bf01012kbz.html 2.http://blog.csdn.net/happyhhb/article/d ...

  3. MFC的消息映射机制揭秘

    MFC的设计者们在设计MFC时,紧紧把握一个目标,那就是尽可能使得MFC的代码要小,速度尽可能快.为了这个目标,他们使用了许多技巧,其中很多技巧体现在宏的运用上,实现MFC的消息映射的机制就是其中之一 ...

  4. vc++窗口的创建过程(MFC消息机制的经典文章)

    一.什么是窗口类  在Windows中运行的程序,大多数都有一个或几个可以看得见的窗口,而在这些窗口被创建起来之前,操作系统怎么知道该怎样创建该窗口,以及用户操作该窗口的各种消息交给谁处理呢?所以VC ...

  5. MFC消息机制

    何谓消息.消息处理函数.消息映射?消息简单的说就是指通过输入设备向程序发出指令要执行某个操作.具体的某个操作是你的一系列代码.称为消息处理函数. 在SDK中消息其实非常容易理解,当窗口建立后便会有一个 ...

  6. MFC六大核心机制之五、六:消息映射和命令传递

    作为C++程序员,我们总是希望自己程序的所有代码都是自己写出来的,如果使用了其他的一些库,也总是千方百计想弄清楚其中的类和函数的原理,否则就会感觉不踏实.所以,我们对于在进行MFC视窗程序设计时经常要 ...

  7. MFC的消息响应机制说明

    MFC的快速理解: 1.MFC的设计者们在设计MFC时,有一个主要的方向就是尽可能使得MFC的代码要小,速度尽可能快.为了这个方向,工程师们使用了许多技巧,主要表现在宏的运用上,实 现MFC的消息映射 ...

  8. 我对windows消息机制的理解(参考深入浅出MFC,欢迎批评指正!!)

    以消息为基础,以事件驱动之 程序的进行依靠外部消息来驱动,即:程序不断等待任何可能的输入,然后做判断,然后再做适当的处理. 消息输入:操作系统捕获,以消息形式进入程序.(操作系统通过其USERS模块中 ...

  9. MFC学习(四) 消息机制

    1 消息机制的要点: 消息队列:先进先出 消息循环:通过循环while,不断的从消息队列中取得队首消息,并分发消息. 消息处理:根据不同的消息类型做不同的处理 事件:事件响应函数 2 消息机制 _tW ...

随机推荐

  1. 什么是TimeTunnel

    index - Taocode 欢迎使用TimeTunnel PageOutline(1-3,,inline) 什么是TimeTunnel !TimeTunnel(简称TT)是一个基于thrift通讯 ...

  2. Fruit Ninja(树状数组+思维)

    Fruit Ninja Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  3. Office 365 - SharePoint 2013 Online之加入App开发工具Napa

    1.新建一个站点集,模板选择开发者模板.例如以下图: 2.确定以后,须要稍等一会儿; 3.点击站点内容,加入app,例如以下图: 4.进入SharePoint Store.选择Napa.例如以下图: ...

  4. freemarker报错之八

    1.错误描写叙述 freemarker.core.ParseException: Encountered "string" at line 21, column 21 in typ ...

  5. Linux之shell编程基础

    一.变量 变量在shell中分为:本地变量.环境变量.位置参数: 本地变量:仅可在用户当前shell生命期的脚本中使用的变量,本地变量随着shell进程的消亡而无效,本地变量在新启动的shell中依旧 ...

  6. Java--格式化输出

    Java的格式化输出等同于String.Format,与C有很大的相似,比如 System.out.printf("%8.2f", x); 在printf中,可以使用多个参数,例如 ...

  7. SuperSocket源码解析之开篇

    一 简介 官方介绍:SuperSocket 是一个轻量级, 跨平台而且可扩展的 .Net/Mono Socket 服务器程序框架.你无须了解如何使用 Socket, 如何维护 Socket 连接和 S ...

  8. LifecyclePhaseNotFoundException(转)

    This error is generated if you try to invoke a build command that Maven does not understand. In gene ...

  9. java.lang.NoClassDefFoundError: org/apache/lucene/analysis/synonym/SynonymFilter

    2013-6-24 13:28:51 org.apache.solr.common.SolrException log 严重: java.lang.NoClassDefFoundError: org/ ...

  10. webview 加载某些网页失败的处理办法(第七条)

    1.添加权限:AndroidManifest.xml中必须使用许可"android.permission.INTERNET",否则会出Web page not available错 ...