深入VCL 理解BCB的消息机制(二)[1]

[入库:2005年8月19日] [更新:2007年3月24日]

本文简介:选择自 cker 的 blog

 

深入vcl 理解bcb的消息机制

方法2

written by
cker

方法2。重载tcontrol的wndproc方法

还是先谈谈vcl的继承策略。vcl中的继承链的顶部是tobject基类。一切的vcl组件和对象都继承自tobject。

打开bcb帮助查看tcontrol的继承关系:

tobject->tpersistent->tcomponent->tcontrol

呵呵,原来tcontrol是从tpersistent类的子类tcomponent类继承而来的。tpersistent抽象基类具有使用流stream来存取类的属性的能力。

tcomponent类则是所有vcl组件的父类。

这就是所有的vcl组件包括您的自定义组件可以使用dfm文件存取属性的原因『当然要是tpersistent的子类,我想您很少需要直接从tobject类来派生您的自定义组件吧』。

tcontrol类的重要性并不亚于它的父类们。在bcb的继承关系中,tcontrol类的是所有vcl可视化组件的父类。实际上就是控件的意思吧。所谓可视化是指您可以在运行期间看到和操纵的控件。这类控件所具有的一些基本属性和方法都在tcontrol类中进行定义。

tcontrol的实现在\borland\cbuilder5\source\vcl\control.pas中可以找到。『可能会有朋友问你怎么知道在那里?使用bcb提供的search -> find in files很容易找到。或者使用第三方插件的grep功能。』

好了,进入vcl的源码吧。说到这里免不了要抱怨一下borland。哎,为什么要用pascal实现这一切.....:-(

tcontrol继承但并没有重写tobject的dispatch()方法。反而提供了一个新的方法就是xycleo提到的wndproc()。一起来看看borland的工程师们是怎么写的吧。

procedure tcontrol.wndproc(var message: tmessage);
var
  form: tcustomform;
begin
//由拥有control的窗体来处理设计期间的消息
  if (csdesigning in componentstate) then
  begin
    form := getparentform(self);
    if (form <> nil) and (form.designer <> nil) and
      form.designer.isdesignmsg(self, message) then exit;
  end
//如果需要,键盘消息交由拥有control的窗体来处理
  else if (message.msg >= wm_keyfirst) and (message.msg <= wm_keylast) then
  begin
    form := getparentform(self);
    if (form <> nil) and form.wantchildkey(self, message) then exit;
  end
//处理鼠标消息
  else if (message.msg >= wm_mousefirst) and (message.msg <= wm_mouselast) then
  begin
    if not (csdoubleclicks in controlstyle) then
      case message.msg of
        wm_lbuttondblclk, wm_rbuttondblclk, wm_mbuttondblclk:
          dec(message.msg, wm_lbuttondblclk - wm_lbuttondown);
      end;
    case message.msg of
      wm_mousemove: application.hintmousemessage(self, message);
      wm_lbuttondown, wm_lbuttondblclk:
        begin
          if fdragmode = dmautomatic then
          begin
            beginautodrag;
            exit;
          end;
          include(fcontrolstate, cslbuttondown);
        end;
      wm_lbuttonup:
        exclude(fcontrolstate, cslbuttondown);
    end;
  end
// 下面一行有点特别。如果您仔细的话会看到这个消息是cm_visiblechanged.
// 而不是我们熟悉的wm_开头的标准windows消息.
// 尽管borland没有在它的帮助中提到有这一类的cm消息存在。但很显然这是bcb的
// 自定义消息。呵呵,如果您对此有兴趣可以在vcl源码中查找相关的内容。一定会有不小的收获。
  else if message.msg = cm_visiblechanged then
    with message do
      senddocknotification(msg, wparam, lparam);
// 最后调用dispatch方法。
  dispatch(message);
end;

看完这段代码,你会发现tcontrol类实际上只处理了鼠标消息,没有处理的消息最后都转入dispatch()来处理。

但这里需要强调指出的是tcontrol自己并没有获得焦点focus的能力。tcontrol的子类twincontrol才具有这样的能力。我凭什么这样讲?呵呵,还是打开bcb的帮助。很多朋友抱怨bcb的帮助实在不如vc的msdn。毋庸讳言,的确差远了。而且这个帮助还经常有问题。但有总比没有好啊。

言归正传,在帮助的the twincontrol branch 分支下,您可以看到关于twincontrol类的简介。指出twincontrol类是所有窗体类控件的基类。所谓窗体类控件指的是这样一类控件:

1. 可以在程序运行时取得焦点的控件。

本文关键:VCL 消息 CKER
  相关方案
Google
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top