BCB消息消息机制
来源:互联网 发布:复杂网络同步 编辑:程序博客网 时间:2024/05/16 18:49
方法1:使用消息映射(Message Map)重载TObject的Dispatch虚成员函数
在\Borland\CBuilder5\Include\Vcl找到sysmac.h,其中有如下的预编译宏定义:
#define BEGIN_MESSAGE_MAP virtual void __fastcallDispatch(void *Message)\
{ \
switch (((PMessage)Message)->Msg) \
{
#define VCL_MESSAGE_HANDLER(msg,type,meth) \
case msg: \
meth(*((type *)Message)); \
break;
//NOTE:ATLdefines a MESSAGE_HANDLER macro which conflicts
{
switch (((PMessage)Message)->Msg)
{
//NOTE:ATL
//with VCL's macro. The VCL macro has been renamed to VCL_MESSAGE_H//ANDLER. If you are not using ATL, MESSAGE_HANDLER is defined as
//in previous versions of BCB.
#if !defined(USING_ATL)&&!defined(USING_ATLVCL)&& !defined (INC_ATL_HEADERS)
#define MESSAGE_HANDLER VCL_MESSAGE_HANDLER
#endif // ATL_COMPAT
#define END_MESSAGE_MAP(base)
default: \
base: ispatch(Message); \
break; \
} \
}
方法2:重载TControl的WndProc方法
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方法。反而提供了一个新的方法
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