delphi VCL研究之消息分发机制(转)
2015-06-04 16:49
344 查看
原文来源,/article/1515622.html
在图中可以看到,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 Code
接着就是界面代码,我们在Application的主Form(Form1)上放入3个按钮,程序界面如图4.2所示。
界面上的3个按钮的名字分别是:btnMsg2000、btnMsg2001、btnMsg2002。该3个按钮用来分发3个消息,将3个消息的值分别定义为2000、2001和2002。
在Form的OnCreate事件中,创建一个TMsgAccepter类的实例。然后,在3个按钮的OnClick事件中分别加上代码,将3个不同的消息分发给TMsgAccepter类的实例对象,以观察TMsgAccepter作出的反应。最后,在Form的OnDestroy事件中,析构TMsgAccepter类的实例对象。完整的界面程序单元代码如下:
在TMsgAccepter类的代码中可以看到,它只能处理编号为2000和2002的消息,而没有编号为2001的消息的处理函数,但它覆盖了TObject的DefaultHandler(),于是就提供了默认的消息处理函数。
运行程序,分别单击3个按钮,得到了3句不同的回答。对于消息2000和2002,TMsgAccepter照单全收,正确识别出所接收到的消息。而只有在接收消息2001时,由于没有提供专门的消息处理函数,导致了对DefaultHandler()的调用。幸运的是,在DefaultHandler中,还可以使用message参数给出的附加信息(TMyMsg记录类型中的MsgText域)。
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(画布)属性。
unit MsgDispTest; interface uses Dialogs, Messages; type TMyMsg = record Msg : Cardinal; MsgText : ShortString; end; TMsgAccepter = class // 消息接收器类 private procedure AcceptMsg2000(var msg : TMyMsg); message 2000; procedure AcceptMsg2002(var msg : TMyMsg); message 2002; public procedure DefaultHandler(var Message); override; //默认处理函数 end; implementation { TMsgAccepter } procedure TMsgAccepter.AcceptMsg2000(var msg: TMyMsg); begin ShowMessage('嗨,我收到了编号为 2000 的消息,它的描述是:' + msg.MsgText); end; procedure TMsgAccepter.AcceptMsg2002(var msg: TMyMsg); begin ShowMessage('嗨,我收到了编号为2002的消息,它的描述是:' + msg.MsgText); end; procedure TMsgAccepter.DefaultHandler(var message); begin ShowMessage('嗨,这个消息我不认识,无法接收,它的描述是:' + TMyMsg(message).MsgText); end; end.
Delphi Code
接着就是界面代码,我们在Application的主Form(Form1)上放入3个按钮,程序界面如图4.2所示。
界面上的3个按钮的名字分别是:btnMsg2000、btnMsg2001、btnMsg2002。该3个按钮用来分发3个消息,将3个消息的值分别定义为2000、2001和2002。
在Form的OnCreate事件中,创建一个TMsgAccepter类的实例。然后,在3个按钮的OnClick事件中分别加上代码,将3个不同的消息分发给TMsgAccepter类的实例对象,以观察TMsgAccepter作出的反应。最后,在Form的OnDestroy事件中,析构TMsgAccepter类的实例对象。完整的界面程序单元代码如下:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,Forms, Dialogs, StdCtrls, MsgDispTest; type TForm1 = 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; var Form1: 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); var Msg : TMyMsg; begin // 将值为2000的消息分发给MsgAccept对象,观察其反应 Msg.Msg := 2000; Msg.MsgText := 'Message 2000'; // 消息的文字描述 MsgAccept.Dispatch(Msg); // 分发消息 end; procedure TForm1.btnMsg2002Click(Sender: TObject); var Msg : TMyMsg; begin // 将值为2002的消息分发给MsgAccept对象,观察其反应 Msg.Msg := 2002; Msg.MsgText := 'Message 2002'; // 消息的文字描述 MsgAccept.Dispatch(Msg); // 分发消息 end; procedure TForm1.btnMsg2001Click(Sender: TObject); var Msg : 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域)。
相关文章推荐
- delphi使用 第三方控件
- 发现个delphi调用vc写的Dll中包含pchar参数报错奇怪现象
- delphi身份证验证
- Delphi之TComponent类
- DELPHI 动态 创建和释放 多个 EDIT 控件
- delphi XE8 正式破解版下载、注册码
- delphi7及控件安装
- Delphi程序的自我修改
- Delphi中TList类应用
- delphi ocx在IE8下调试不能断点的问题
- Delphi 2007 一段代码手工折叠
- 使用Delphi实现JNI - 实例
- Delphi TcxComboBox控件说明
- 在delphixe7 编写dll中发现的问题s
- 使用Delphi实现JNI - 3
- 使用Delphi实现JNI - 2
- Delphi编译选项
- Delphi 快捷键
- Delphi webservices 传数据
- Delphi TClientDataSet的使用