读书人

delphi VCL研究之讯息分发机制-delphi

发布时间: 2013-03-06 16:20:31 作者: rapoo

delphi VCL研究之消息分发机制-delphi高手突破读书笔记
1.VCL 概貌

先看一下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(画布)属性。

delphi VCL研究之讯息分发机制-delphi高手突破读书笔记

图4.1 VCL类图主要分支(深色表示核心分支)

2.TObject与消息分发

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

unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics,Controls,Forms, Dialogs, StdCtrls, MsgDispTest;typeTForm1 = class(TForm)btnMsg2000: TButton;btnMsg2001: TButton;btnMsg2002: TButton;Label1: TLabel;procedure FormCreate(Sender: TObject);procedure FormDestroy(Sender: TObject);procedure btnMsg2000Click(Sender: TObject);procedure btnMsg2002Click(Sender: TObject);procedure btnMsg2001Click(Sender: TObject);end;varForm1: TForm1;MsgAccept : TMsgAccepter; // 自定义的消息接收类implementation{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject);begin// 创建TMsgAccepter类的实例MsgAccept := TMsgAccepter.Create();end;procedure TForm1.FormDestroy(Sender: TObject);begin// 析构TMsgAccepter类的实例MsgAccept.Free();MsgAccept := nil;end;procedure TForm1.btnMsg2000Click(Sender: TObject);varMsg : TMyMsg;begin// 将值为2000的消息分发给MsgAccept对象,观察其反应Msg.Msg := 2000;Msg.MsgText := 'Message 2000'; // 消息的文字描述MsgAccept.Dispatch(Msg); // 分发消息end;procedure TForm1.btnMsg2002Click(Sender: TObject);varMsg : TMyMsg;begin// 将值为2002的消息分发给MsgAccept对象,观察其反应Msg.Msg := 2002;Msg.MsgText := 'Message 2002'; // 消息的文字描述MsgAccept.Dispatch(Msg); // 分发消息end;procedure TForm1.btnMsg2001Click(Sender: TObject);varMsg : TMyMsg;begin// 将值为2001的消息分发给MsgAccept对象,观察其反应Msg.Msg := 2001;Msg.MsgText := 'Message 2001'; // 消息的文字描述MsgAccept.Dispatch(Msg); // 分发消息end;end.

在TMsgAccepter类的代码中可以看到,它只能处理编号为2000和2002的消息,而没有编号为2001的消息的处理函数,但它覆盖了TObject的DefaultHandler(),于是就提供了默认的消息处理函数。
运行程序,分别单击3个按钮,得到了3句不同的回答。对于消息2000和2002,TMsgAccepter照单全收,正确识别出所接收到的消息。而只有在接收消息2001时,由于没有提供专门的消息处理函数,导致了对DefaultHandler()的调用。幸运的是,在DefaultHandler中,还可以使用message参数给出的附加信息(TMyMsg记录类型中的MsgText域)。

读书人网 >.NET

热点推荐