深度剖析消息反射机制

原创 2003年07月03日 15:48:00

    摘要:在前面我们分析了控件通知消息WM_NOTIFY,和WM_NOTIFY紧密联系的还有一个MFC新特性:消息反射。本文中,我想就这个问题作一个全面的论述,如果有错误,还望各路大虾批评指正。

    什么是消息反射?
    在windows里面,子控件经常向父控件发送消息,例如很多子控件要绘制自己的背景,就可能向父窗口发送消息WM_CTLCOLOR。对于从子控件发来的消息,父控件有可能在处理之前,把消息返还给子控件处理,这样消息看起来就想是从父窗口反射回来一样,故此得名:消息反射。

    消息反射的由来
    在windows和MFC4.0版本一下,父窗口(通常是一个对话框)会对这些消息进行处理,换句话说,自控件的这些消息处理必须在父窗口类体内,每当我们添加子控件的时候,就要在父窗口类中复制这些代码,我们可以想象这是多么的复杂,代码是多么的臃肿!
    我们可以想象,如果这些消息都让父窗口类去做,父窗口就成了一个万能的神,一个臃肿不堪的代码机,无论如何消息的处理都集中在父窗口类中,会使父窗口繁重无比,但是子控件却无事可做,并且代码也无法重用,这对于一个程序员来讲是多么痛苦的一件事?!
    在老版本的MFC中,设计者也意识到了这个问题,他们对一些消息采用了虚拟机制,例如:WM_DRAWITEM,这样子控件就有机会控制自己的动作,代码的可重用性有了一定的提高,但是这还没有达到大部分人的要求,所以在高版本的MFC中,提出了一种更方便的机制:消息反射。
    通过消息反射机制,子控件窗口便能够自行处理与自身相关的一些消息,增强了封装性,同时也提高了子控件窗口类的可重用性。不过需要注意的是:消息反射是MFC实现的,不是windows实现的;要让你的消息反射机制工作,你得类必须从CWnd类派生。

    Message-Map中的处理
    如果想要处理消息反射,必须了解相应的Message-Map宏和函数原型。一般来讲,Message-Map是有一定的规律的,通常她在消息的前面加上一个ON_ ,然后再消息的最后加上 _REFLECT。例如我们前面提到的WM_CTLCOLOR 经过处理后变成了ON_WM_CTLCOLOR_REFLECT;WM_MEASUREITEM则变成了ON_WM_MEASUREITEM_REFLECT。
    凡事总会有例外,这里也是这样,这里面有3个例外:
    (1) WM_COMMAND 转换成 ON_CONTROL_REFLECT;
    (2) WM_NOTIFY  转换成 ON_NOTIFY_REFLECT;
    (3) ON_UPDATE_COMMAND_UI 转换成 ON_UPDATE_COMMAND_UI_REFLECT;
    对于函数原型,也必须是以 afx_msg 开头。

    利用ClassWizard添加消息反射
    (1)在ClassWizard中,打开选择项Message Maps;
    (2)在下拉列表Class name中选择你要控制的类;
    (3)在Object IDs中,选中相应的类名;
    (4)在Messages一栏中找到前面带有=标记的消息,那就是反射消息;
    (5)双击鼠标或者单击添加按钮,然后OK!

    消息处理的过程
  (1)子窗口向父窗口发送通知消息,激发父窗口去调用它的虚函数CWnd::OnNotify。大致的结构如下
       BOOL CWnd::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
       {
          if (ReflectLastMsg(hWndCtrl, pResult)) file://hWndCtrl,为发送窗口
                                    return TRUE; file://如果子窗口已处理了此消息,返回
          AFX_NOTIFY notify;
          notify.pResult = pResult;
          notify.pNMHDR = pNMHDR;
          return OnCmdMsg(nID, MAKELONG(nCode, WM_NOTIFY)? notify:NULL);
      }
  (2)ReflectLastMsg声明如下:static BOOL PASCAL ReflectLastMsg(HWND hWndChild, LRESULT* pResult = NULL);
     它的主要任务就是调用发送窗口的SendChildNotifyLastMsg。
  (3)SendChildNotifyLastMsg声明如下:BOOL SendChildNotifyLastMsg(LRESULT* pResult = NULL);
     调用发送窗口的虚函数OnChildNotify函数,进行处理。 如果发送窗口没有进行重载处理,则调用ReflectChildNotify(...)函数进行标准的反射消息的消息映射处理。

    使用的一个例子
   
这里面我们举一个简单的例子,希望大家能够更清晰的掌握消息反射机制。
    (1)创建一个基于对话框的工程。
    (2)利用向导创建一个新的类:CMyEdit,基类是CEdit。
    (3)在CMyEdit头文件中加入3个成员变量:
         COLORREF m_clrText ;
 COLORREF m_clrBkgnd ;
 CBrush   m_brBkgnd;
    (4)利用向导在其中加入WM_CTLCOLOR(看到了么,前面是不是有一个=?),并且将它的函数体改为:
         HBRUSH CMyEdit::CtlColor(CDC* pDC, UINT nCtlColor)
        {
  pDC->SetTextColor( m_clrText );    // text
  pDC->SetBkColor( m_clrBkgnd );    // text bkgnd
  return m_brBkgnd;                // ctl bkgnd
        }
        同时我们在.cpp文件中会看到ON_WM_CTLCOLOR_REFLECT(),这就是我们所说的经过处理的宏,是不是很符合规则?
    (5)在对话框中加入一个Edit,增加一个关联的变量,选择Control属性,类别为CMyEdit。
    (6)在对话框.cpp文件中加入#include "MyEdit.h",运行,看到了什么?呵呵。
   
     事情到了一个阶段,希望你能够喜欢,明天见!

Kafka源码深度解析-系列1 -消息队列的策略与语义

-Kafka关键概念介绍 -消息队列的各种策略与语义作为一个消息队列,Kafka在业界已经相当有名。相对传统的RabbitMq/ActiveMq,Kafka天生就是分布式的,支持数据的分片、复制以及...
  • chunlongyu
  • chunlongyu
  • 2016年09月14日 15:23
  • 3967

DuiLib消息处理剖析

本来想自己写写duilib的消息机制来帮助duilib的新手朋友,不过今天发现已经有人写过了,而且写得很不错,把duilib的主干消息机制都说明了,我就直接转载过来了,原地址:http://blog....
  • zhuhongshu
  • zhuhongshu
  • 2014年12月04日 16:00
  • 6818

深入理解java反射机制

一,java的核心机制java有两种核心机制:java虚拟机(JavaVirtual Machine)与垃圾收集机制(Garbage collection): Java虚拟机:是运行所有Java...
  • u012585964
  • u012585964
  • 2016年07月24日 02:32
  • 6444

深度剖析消息反射机制

深度剖析消息反射机制 作者:hustli     摘要:在前面我们分析了控件通知消息WM_NOTIFY,和WM_NOTIFY紧密联系的还有一个MFC新特性:消息反射。本文中,我想就这个问题作一个全...
  • xiexievv
  • xiexievv
  • 2011年03月27日 21:36
  • 1976

黑马程序员————JAVA反射机制深度剖析

本文通过对反射技术来讲解方法反射,属性反射,数组反射,构造器反射,还有与其相关的方法句柄...
  • QSXEDC
  • QSXEDC
  • 2015年09月26日 14:37
  • 341

java反射机制深度剖析

Java反射机制是Java语言中一种很重要的机制,可能在工作中用到的机会不多,但是在很多框架中都有用到这种机制。我们知道Java是一门静态语言,在程序编译时变量的数据类型都已经确定,那么在Java运行...
  • zalan01408980
  • zalan01408980
  • 2018年01月08日 23:00
  • 4

JavaSE第六十一讲:Java反射机制深度剖析

1. Java中的反射是所有以后学习框架的基础,java中的反射是Java中难点和重点。 Java语言的反射 1. 在Java运行时环境中,对于任意一个类,能否知道这个类有哪些属性和方法?对于...
  • xukunhui2
  • xukunhui2
  • 2012年12月30日 17:39
  • 947

Java反射机制剖析(四)-深度剖析动态代理原理及总结

动态代理类原理(示例代码参见java反射机制剖析(三)) a)  理解上面的动态代理示例流程 b)  代理接口实现类源代码剖析 咱...
  • ccecwg
  • ccecwg
  • 2014年11月26日 15:14
  • 279

Java反射机制剖析(四)-深度剖析动态代理原理及总结

转自http://blog.csdn.net/lfsf802/article/details/7239799 动态代理类原理(示例代码参见java反射机制剖析(三)) a)  ...
  • fendou4533
  • fendou4533
  • 2013年03月05日 09:53
  • 711

Java反射机制剖析(四)-深度剖析动态代理原理及总结

a)  理解上面的动态代理示例流程 b)  代理接口实现类源代码剖析 咱们一起来剖析一下代理实现类($Proxy0)的源代码和整个动态代理的...
  • woshisen6841015
  • woshisen6841015
  • 2014年04月24日 13:45
  • 335
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度剖析消息反射机制
举报原因:
原因补充:

(最多只允许输入30个字)