当前位置:首页 > Windows程序 > 正文

delphi VCL研究之消息分发机制(转)

2021-05-26 Windows程序

先看一下VCL类图的主要分支,如图4.1所示。
在图中可以看到,TObject是VCL的祖先类,这也是Object Pascal语言所规定的。但实际上,TObject以及TObject声明所在的system.pas整个单元,包括在“编译器魔法”话题中提到的_ClassCreate等函数,都是编译器内置支持的。因此,无法修改、删除system.pas中的任何东西,也无法将system.pas加入你的project,否则会得到“Identifier redeclared ‘system’”的错误提示,因project中已经被编译器自动包含了system单元。
意思是,TObject是Object Pascal语言/编译器本身的一个性质!

TObject封装了Object Pascal类/对象的最基本行为。
TPersistent派生自TObject,TPersistent使得自身及其派生类对象具有自我保存、持久存在的能力。
TComponent派生自TPersistent,这条分支之下所有的类都可以被称为“组件”。组件的一般特性是:
(1)可出现在开发环境的“组件板”上。

(2)能够拥有和管理其他组件。

(3)能够存取自身(这是因为TComponent派生自TPersistent)。
TControl派生自TComponent,其分支之下所有的类,都是在运行时可见的组件。
TWinControl派生自TControl,这个分支封装了Windows系统的屏幕对象,也就是一个真正的Windows窗口(拥有窗口句柄)。
TCustomControl派生自TwinControl。从TCustomControl开始,组件拥有了Canvas(画布)属性。

技术分享

2.TObject与消息分发

首先来看一下TObject这个“万物之源”究竟长得何等模样。它的声明如下:

1 TObject = class 2 constructor Create; 3 procedure Free; 4 class function InitInstance(Instance: Pointer): TObject; 5 procedure CleanupInstance; 6 function ClassType: TClass; 7 class function ClassName: ShortString; 8 class function ClassNameIs(const Name: string): Boolean; 9 class function ClassParent: TClass; 10 class function ClassInfo: Pointer; 11 class function InstanceSize: Longint; 12 class function InheritsFrom(AClass: TClass): Boolean; 13 class function MethodAddress(const Name: ShortString): Pointer; 14 class function MethodName(Address: Pointer): ShortString; 15 function FieldAddress(const Name: ShortString): Pointer; 16 function GetInterface(const IID: TGUID; out Obj): Boolean; 17 class function GetInterfaceEntry(const IID: TGUID): PInterfaceEntry; 18 class function GetInterfaceTable: PInterfaceTable; 19 function SafeCallException(ExceptObject: TObject; 20 ExceptAddr: Pointer): HResult; virtual; 21 procedure AfterConstruction; virtual; 22 procedure BeforeDestruction; virtual; 23 procedure Dispatch(var Message); virtual; 24 procedure DefaultHandler(var Message); virtual; 25 class function NewInstance: TObject; virtual; 26 procedure FreeInstance; virtual; 27 destructor Destroy; virtual; 28 end;

Delphi Code

       从TObject的声明中可以看到,TObject包含了诸如实例初始化、实例析构、RTTI、消息分发等相关实现的方法。现在就来研究一下TObject与消息分发,这也是VCL对Windows消息封装的模型基础。
      在TObject类中,有一个Dispatch()方法和一个DefaultHandler()方法,它们都是与消息分发机制相关的。
Dispatch()负责将特定的消息分发给合适的消息处理函数。首先它会在对象本身类型的类中寻找该消息的处理函数,如果找到,则调用它;如果没有找到而该类覆盖了TObject的DefaultHandler(),则调用该类的DefaultHandler();如果两者都不存在,则继续在其基类中寻找,直至寻找到TObject这一层,而TObject已经提供了默认的DefaultHandler()方法。
      先来看一个示例程序,它演示了消息分发及处理的过程。
首先自定义一个消息结构TMyMsg,它是我们自定义的消息记录类型。对于自定义的消息类型,VCL只规定它的首4字节必须是消息编号,其后的数据类型任意。同时,VCL也提供了一个TMessage类型用于传递消息。在此程序中,不使用TMessage,,而用TMyMsg代替:

温馨提示: 本文由Jm博客推荐,转载请保留链接: https://www.jmwww.net/file/71308.html