方法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()来处理。
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器