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. 修复ubuntu播放wmv等视频没有声音问题

    1. Mplayer or SMplayer 1.1 原因: 很可能是你没有安装 w32codes 1.2 解决方法: (1)下载 w32codes 官方站点 all-20110131.tar.bz2 ...

  2. Eclipse3.6 添加JUnit源代码

    Eclipse中无法查看JUnit源代码,也无法设置源代码的jar. 解决方法: 1.  下载org.junit.source_4.8.1.v4_8_1_v20100427-1100.jar,放到ec ...

  3. CocoaPods on Xcode 6 and Yosemite

    老子今天又给环境跪了..... cocoapods 在升级完新系统以后无法工作 解决cocoapods 在 mac 10.10下报错 错误例如以下. /System/Library/Framework ...

  4. C Primer Plus 读书笔记之C基础回顾

    目标代码文件.可执行文件和库 C编程的基本策略是使用程序将源代码文件转换为可执行文件,此文件包含可以运行的机器语言代码.C分两步完成这一工作:编译和链接.编译器将源代码转换为中间代码,链接器将此中间代 ...

  5. BZOJ 3505: [Cqoi2014]数三角形( 组合数 )

    先n++, m++ 显然答案就是C(3, n*m) - m*C(3, n) - n*C(3, m) - cnt. 表示在全部点中选出3个的方案减去不合法的, 同一行/列的不合法方案很好求, 对角线的不 ...

  6. dsdfdsfd

    aibang.com/show/1816725179-1268699976/product/7069113.html aibang.com/show/1816725179-1268699976/pro ...

  7. Unity Interface Serialization-Expose Interface field In Inspector

    Unity has some quirks about their inspector, so as a preface they are listed here: If you add a [Ser ...

  8. Vbox视图热键

    Vbox屏幕热键 在Vbox中一般host主键会默觉得"右Ctrl",例如以下图所看到的,在选择自己主动调整窗体后,"视图"选项栏会消失.这时若想更改视图设置能 ...

  9. Android使用学习之画图(Canvas,Paint)与手势感应及其应用(乒乓球小游戏)

    作为一个没有学习Android的菜鸟,近期一直在工作之外努力地学习的Android的使用. 这周看了下Android的画图.主要是Canvas,Paint等,感觉须要实践下.下午正好有空,就想整一个乒 ...

  10. 浅谈PPM (Project Portfolio Management) - 1

    前言: 本文以纯理论性的PPM解说为主,不会涉及到具体怎样实施,我会在以后介绍具体的PPM实施方案介绍. PPM,可能非常多人并不清楚甚至可能没听说过,这是一个近些年才流行起来的概念,是Project ...