zoukankan      html  css  js  c++  java
  • VCL定义和使用CM_Message的原因(主要是内部控制,同时可简化参数传递,还可截住消息,统一走消息路线,还可省内存)

    内部控制是指,做了某些操作后产生某些效果,但是Windows系统本身不提供这样的消息,应此不得不自定义。比如父窗口改变了字体,那么所有子窗口也都应该改变字体,至少也得通知一下它们,让子控件自己决定是否响应以及怎么响应(替代了虚函数的作用,但是消息更加干净利落,愿不愿意以及怎么做完全由对方决定),但是Windows不提供这样的消息,于是自定义消息CM_PARENTFONTCHANGED闪亮登场。VCL当然也可以定义一个函数,然后直接去执行这个函数达到目的,但是参数的个数以及类型就成了问题,处理函数的时机的灵活性就成了问题,等等,而使用消息的话,这些问题都不存在,并且还有利于不同VCL版本的兼容(比如换个消息对应的函数名)。此外,需要强调的是,这些消息并不是SendMessage发送的,大多数仍是Perform执行的(需要稍加统计进行确认),因此实际上这些”消息“并没有经过Windows系统进行中转处理,而是会被直接执行,因此不会造成执行时的延迟。

    -----------------------------------------------------------------

    问题:最近看VCL源码,看到经常需要发送CM_消息去调用某个函数,我就不明白,为什么要这样。直接调用函数名称不是挺好吗,尤其是调用虚函数的话,一样很灵活。而且发消息还有个缺点,更依赖于系统,如果系统正忙怎么办?而虚函数只和语言自己有关系,不是更稳妥可靠吗?为什么要自定义消息呢?还把VCL框架搞的更复杂了。

    比如:
    procedure TWinControl.SetBorderWidth(Value: TBorderWidth);
    begin
    if FBorderWidth <> Value then
    begin
    FBorderWidth := Value;
    Perform(CM_BORDERCHANGED, 0, 0); // 这里直接调用函数名称不好吗?
    end;
    end;

    procedure TWinControl.CMBorderChanged(var Message: TMessage);
    begin
    inherited;
    if HandleAllocated then
    begin
    SetWindowPos(Handle, 0, 0,0,0,0, SWP_NOACTIVATE or
    SWP_NOZORDER or SWP_NOMOVE or SWP_NOSIZE or SWP_FRAMECHANGED);
    if Visible then
    Invalidate;
    end;
    end;

    ----------------------------------------------------------------
    回答:
    1. Perform是直接调用WindowProc函数,同步调用没有系统忙不忙之说。相当于SendMessage。不发消息直接调用函数倒也行,不过系统的消息处理总是要处理的。不如就统一走消息这条路了。
    2. 最主要是参数的简洁,Perform函数会把三个参数重新组织成一个消息,然后发给其它函数的时候TMessage就可以作为一个整体发给别的函数了,这样还方便写消息索引函数,虚函数与消息的对应没有消息索引函数来的明显。根据传来的三个参数来构建一个消息,这也许是使用CM的关键原因。否则:
    1)每个虚函数都需要三个参数写起来还不烦死,看起来烦,写起来也烦(函数参数的简洁)
    2)即使可以传递三个参数给虚函数,虽然可以,但是不够通用,发消息的话只要对应消息索引即可,后两个参数被内包含了,这样不必仅仅为lparam和wparam的不同写上多个不同的虚函数。不如就统一走消息这条路了(函数个数的简洁)。
    3)或者想节省函数的参数个数,并直接调用消息处理函数也是一样的效果,这样的话每个发送方都组装一遍也很烦,这样代码就重复了,这里可以统一使用Perform可避免重复组装的问题,这样代码显得相当地简洁(VCL库代码的简洁)
    3. 发消息还可以在WndProc里截住并单独处理,不必单独写成函数,虚函数不行,只能单独写(函数个数的简洁,使用时候的简洁)
    4. 另外消息函数实际是动态函数,如果子类派生层次比较多的话比虚函数在内存上是要节省一些的。而用法和虚函数又差不多。当然,在Delphi下虚函数也可使用dynamic达到与消息索引函数相同的效果。但是无论如何,消息函数恰好也是节省内存的,那就更有理由使用了(内存的简洁)。

    总结:
    因参数个数的原因,统一走消息路线,好像是很正确的理解。
    ----------------------------------------------------------------

    不是理由的理由:
    消息可以跨进程,虚函数能吗
    ----------------------------------------------------------------

    进一步提问:

    都说的在理。不过为啥要统一走消息啊,自定义消息累不累啊,而且我看有些地方也是调用虚函数的,也不在少数。不过Borland有意搞这个自定义消息,应该还是别有用意?能不能挖空心思再想想啊。另外,我有空把它全部改成虚函数试试,看看编出来的程序还会正确执行不?这不失为一次对OO深刻理解的尝试。

    回答:
    有没有深意看其它VCL源码,打开VCL所有源码,可以看到CM消息的所有使用情况。不过上面应该已经猜得八九不离十。
    ----------------------------------------------------------------

    参考:
    http://bbs.csdn.net/topics/390888872

    -----------------------------------------------------------------

    有些可能是为了整个vcl的速度
    用虚函数方法会增加vmt的长度,减慢vcl的速度

    其实估计是参数构造原因,以及减小内存的原因。

    你知道,消息只要有句柄就能发过去
    想对使用环境,更减少耦合,
    比如一个控件,我只知道句柄,我要执行它的方法
    那只能用消息传递,

  • 相关阅读:
    zrep 0.9 发布,zfs文件系统复制和故障转移
    Silverlight实例教程 Out of Browser开篇
    Silverlight Analytics Framework(开源分析框架)
    让你的Silverlight程序部署在任意服务器上
    Silverlight 4简体中文正式版脱机帮助文档下载
    Silverlight实例教程 Out of Browser存取本地文件系统
    Silverlight获取子控件和父控件方法
    轻松创建Silverlight 4开发环境
    Silverlight 4新控件PivotViewer介绍
    Silverlight实例教程 Out of Browser配置,安装和卸载
  • 原文地址:https://www.cnblogs.com/findumars/p/4021350.html
Copyright © 2011-2022 走看看