zoukankan      html  css  js  c++  java
  • 关于MFC消息的总结

    一、MFC的消息类型

    MFC的消息类型大致可以分为三种:

    1.命令消息。由菜单和工具栏或快捷键产生,以WM_COMMAND形式发出(以WM_COMMAND发出的还有很多控件,如Button等,但它们产生的不是命令消息,是通知消息)

    命令消息的消息宏是:ON_COMMAND(id,memberFxn)

    2.窗口消息。由系统产生,典型特征是以WM_开头(WM_COMMAND除外)。此类消息映射宏前缀为“ON_WM_”,并且没有参数,因为不管是消息本身还是响应函数都与WM_XXX一一对应了

    3.通知消息。这类消息类型很多,也是最麻烦的。通常以WM_COMMAND或WM_NOTIFY形式发送。通知消息是由子控件发送给父窗口的。

    WM_COMMAND形式是为了兼容以前的格式,因为MFC4.0之前都是以命令消息当作通知消息传递,后来子控件增多,不够用,所以增加了WM_NOTIFY,但为了向前兼容,仍然保留了WM_COMMAND消息,所以制造可麻烦。

    父窗口处理通知消息的消息宏因此就分为两类:

    WM_COMMAND形式的:ON_CONTROL(wNotifyCode,id,memberFxn)或ON_CONTROL_RANGE(wNotifyCode,id,idLast,memberFxn),该宏扩展后发现第一个参数就是WM_COMMAND。所以说ON_CONTROL宏是为了向前兼容的老用法了。

    WM_NOTIFY形式的:ON_NOTIFY(wNotifyCode,id,memberFxn)或ON_NOTIFY_RANGE(wNotifyCode,id,idLast,memberFxn),该宏扩展后发现第一个参数就是WM_NOTIFY。

    但是通常我们很少看到这两个宏,而是被类似ON_BN_CLICKED(id,memberFxn)这样的替换了。实际上这也是一种宏,这种宏展开后还是使用了ON_CONTROL或者ON_NOTIFY宏。只是把参数一wNotifyCode通知码改变成了更容易理解的BN_CLICKED罢了。

    通知消息的一个很重要的特性是反射机制。只有继承CWnd的类有反射机制,通知消息有反射机制,占大多数,但其它有的消息也具有反射性,因为消息反射性的存在主要是为了方便改变子控件本身的某种特性,因此如WM_CTLCOLOR也具有反射性。查看某个消息是不是具有反射性,只需进入类向导中查看消息选项内部,该消息前有没有=号,有则代表有反射性。

    反射机制的工作原理是:子控件产生通知消息后,首先发送给父窗口,让父窗口先处理。但是如果子窗口也具有处理该通知消息的能力,父窗口就将该消息返回给子窗口处理(即子窗口有优先处理自身消息的能力),如果子窗口处理后,消息结束,不再发给父窗口。否则,如果子窗口不具备处理该消息的能力,那么父窗口来处理,如果父窗口也无法处理,再往上抛,直到被处理或抛弃为止。

    但是如果子窗口处理后,还想让父窗口处理,那么子窗口处理函数最后一定要reurn FALSE表示该消息没有被处理(实际上已经处理了),让父窗口接着处理。

    那么子窗口处理这种反射回的信号的宏是什么呢?

    就是ON_CONTROL_REFLECT_EX(wNotifyCode,memberFxn)和ON_NOTIFY_REFLECT_EX(wNotifyCode,memberFxn),memberFxn的返回值是BOOL,要改过来。

    最后讲一讲通知码的问题:

    参数wNotifyCode就是通知码,它标识着子控件发生了什么(比如按钮是被点击(BN_CLICKED)了,还是双击(BN_DOUBLECLICKED)了,还是失去焦点(BN_KILLFOCUS)),也可以看成消息,但是与WM_LBUTTONDBLCLK不是一回事,前者是通知消息的参数是告诉父窗口子窗口被双击了,后者是不需要告诉父窗口的,子窗口可以自己进行处理的消息)

    还有一类宏是负责菜单项等是否可用的,下次再讲。

    总之:

    1.本文最主要的目的是让人看到消息映射宏后知道处理的是哪种类型的消息;

    还有个问题就是为什么按钮的消息响应函数写在父窗口类中?

    原因很简单,因为按钮是子控件,子窗口其实有处理通知消息的优先权,但是一般它不处理(除非你重载),所以就交给父类处理了。本来通知消息也是首先发送给父类的,只是父类又返回给了子控件,这样做是为了强调父窗口的控制权威。就跟很多事情基层做报告,报告拿到上级批准了,才允许执行一样,其实报告本身还是基层做的,只是显示了上级的权威性,控制性。

     

  • 相关阅读:
    2020Java面试题整理
    Oracle中使用Merge Into去除数据库重复记录
    Oracle修改sort_area_size,workarea_size_policy
    免费接口
    Java 将日期或秒数转换为日时分秒,如:2天3小时23分32秒
    linux环境下Mysql不区分大小写配置
    Oracle分区测试
    JS倒计时刷新页面
    JS获取table列数据
    Sql Server 2008日志清理
  • 原文地址:https://www.cnblogs.com/zhuluqing/p/8672537.html
Copyright © 2011-2022 走看看