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. Dreamer2.1 发布 新增将Bean解析成xml和json

    一个上午,增加两个功能 1.直接将对象解析成XML 2.将对象解析成JSON 对象可以是数组,可以是集合,也可以是单个对象 源码和jar下载地址:http://pan.baidu.com/share/ ...

  2. HDU 1432 Lining Up (POJ 1118)

    枚举,枚举点 复杂度为n^3. 还能够枚举边的,n*n*log(n). POJ 1118 要推断0退出. #include<cstdio> #include<cstring> ...

  3. Android中如何查找内存泄露

    1.首先确定是否有内存泄露及哪个程序造成. 1.1.内存泄露已弹出out of memory对话框的情况. 这种情况很简单,直接看对话框就知道是哪个应用的问题了.然后再分析该应用是否是因为内存泄露造成 ...

  4. android的animator

    3.0 以前,android支持两种动画模式,tween animation,frame animation,在android3.0中又引入了一个新的动画系统:property animation,这 ...

  5. jfinal集成spring cxf做webservice服务

    链接地址:http://zhengshuo.iteye.com/blog/2154047 废话不说,直接上代码 新增cxf的plugin CXFPlugin package com.jfinal.pl ...

  6. [转]SELinux管理与配置

    原文链接:http://blog.csdn.net/huangbiao86/article/details/6641893 1.1 SElinux概述 SELinux(Security-Enhance ...

  7. Python 第九篇:队列Queue、生产者消费者模型、(IO/异步IP/Select/Poll/Epool)、Mysql操作

    Mysql操作: grant select,insert,update,delete on *.* to root@"%" Identified by "123456&q ...

  8. USACO 2005 January Gold The Wedding Juicer

    题目 题目链接,我只在poj上找到了题目,usaco居然上不去. 大意就是说有一些\(1\times 1\times 1\)的小方块堆在一起,问最多能装多少水. 我们在一次测试中出了这题,由于我写水题 ...

  9. bzoj 2623 所罗门的咒语

    这一题其实我没做出来.... 我只是想吐吐槽. 题目要求识别验证码,而且连一点特征信息都不给! 我去偷看了一下数据,然后根据数据生成了图片: 我相信当年没有人能拿分吧. 贴一下transform.cp ...

  10. xend调用xenstore的出错揭秘

    近期发现几例问题,均是xend里面报了同一个错误 File "/usr/lib64/python2.4/site-packages/xen/xend/xenstore/xstransact. ...