没有合适的资源?快使用搜索试试~ 我知道了~
Delphi高手突破-04VCL库
需积分: 9 6 下载量 127 浏览量
2012-03-29
18:12:15
上传
评论
收藏 788KB PDF 举报
温馨提示
试读
57页
Delphi高手突破-04VCL库
资源推荐
资源详情
资源评论
Delphi 高手突破
VCL——Visual Component Library,是 Delphi 的基石。Delphi 的优秀,很大程度上得
益于 VCL 的优秀。
VCL 是 Delphi 所提供的基本组件库,也就是所谓的 Application Framework,它对
Windows API(应用程序接口)进行了全面封装,为桌面开发(不限于桌面开发)提供了
整套的解决方案,使得程序员可以在不知晓 API 的情况下进行 Windows 编程。
不过,作为专业的程序员,不知晓 API 是不可能的。VCL 还是一个 Framework(应用
程序框架),可以将 VCL 作为一个平台,程序员在其基础上构建应用程序,便可以忽略很
多系统 API 的细节,而使得开发速度更快。
VCL 的组件也不同于 ActiveX 控件,VCL 组件通过源代码级连接到可执行文件中,因
此其速度更快。而且,企业版的 Delphi 带有全部 VCL 库的源代码,这样程序员不单单可
以知道如何使用 VCL 组件,更可以了解其运行机制与构架。
了解 VCL 的构架,无论对于编写自己的 Application,还是设计程序框架,或者创建自
己的组件/类融入 VCL 构架中,都是必需和大有裨益的。
这也符合某种规律:在学习的时候,求甚解;而在应用的时候,则寻找捷径。Delphi
和 VCL 都能满足这两种需求,因为使用它
Ø 可以不隐藏任何想知道的细节;
Ø 可以忽略不想知道的细节。
在本章中,将带游历 VCL 库的核心,剖析 VCL 的代码。从此,VCL 对您来说不会再
是神秘而艰涩的,因为带领读者它们同样是用代码铸造成的。
4.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 是属于编译器的特性!
TObject 封装了 Object Pascal 类/对象的最基本行为。
TPersistent 派生自 TObject,TPersistent 使得自身及其派生类对象具有自我保存、持久
存在的能力。
TComponent 派生自 TPersistent,这条分支之下所有的类都可以被称为“组件”。组件
的一般特性是:
(1)可出现在开发环境的“组件板”上。
·66·
Click to buy NOW!
P
D
F
-
X
C
h
a
n
g
e
V
i
e
w
e
r
w
w
w
.
d
o
c
u
-
t
r
a
c
k
.
c
o
m
Click to buy NOW!
P
D
F
-
X
C
h
a
n
g
e
V
i
e
w
e
r
w
w
w
.
d
o
c
u
-
t
r
a
c
k
.
c
o
m
VCL 库
4
TWinControl
TControl
TApplication
TStringList
TComponent
TStrings
TObject
TPersistent TRegistry
……
TGraphicControl
TCustomControl
图 4.1 VCL 类图主要分支(深色表示核心分支)
(2)能够拥有和管理其他组件。
(3)能够存取自身(这是因为 TComponent 派生自 TPersistent)。
TControl 派生自 TComponent,其分支之下所有的类,都是在运行时可见的组件。
TWinControl 派生自 TControl,这个分支封装了 Windows 系统的屏幕对象,也就是一
个真正的 Windows 窗口(拥有窗口句柄)。
TCustomControl 派生自 TwinControl。从 TCustomControl 开始,组件拥有了 Canvas(画
布)属性。
从 4.2 节开始,将会先后结合 VCL 中一些核心类的实现代码来了解它们。
4.2 TObject 与消息分发
首先来看一下 TObject 这个“万物之源”究竟长得何等模样。它的声明如下:
TObject = class
constructor Create;
procedure Free;
class function InitInstance(Instance: Pointer): TObject;
procedure CleanupInstance;
function ClassType: TClass;
·67·
Click to buy NOW!
P
D
F
-
X
C
h
a
n
g
e
V
i
e
w
e
r
w
w
w
.
d
o
c
u
-
t
r
a
c
k
.
c
o
m
Click to buy NOW!
P
D
F
-
X
C
h
a
n
g
e
V
i
e
w
e
r
w
w
w
.
d
o
c
u
-
t
r
a
c
k
.
c
o
m
Delphi 高手突破
class function ClassName: ShortString;
class function ClassNameIs(const Name: string): Boolean;
class function ClassParent: TClass;
class function ClassInfo: Pointer;
class function InstanceSize: Longint;
class function InheritsFrom(AClass: TClass): Boolean;
class function MethodAddress(const Name: ShortString): Pointer;
class function MethodName(Address: Pointer): ShortString;
function FieldAddress(const Name: ShortString): Pointer;
function GetInterface(const IID: TGUID; out Obj): Boolean;
class function GetInterfaceEntry(const IID: TGUID):
PInterfaceEntry;
class function GetInterfaceTable: PInterfaceTable;
function SafeCallException(ExceptObject: TObject;
ExceptAddr: Pointer): HResult; virtual;
procedure AfterConstruction; virtual;
procedure BeforeDestruction; virtual;
procedure Dispatch(var Message); virtual;
procedure DefaultHandler(var Message); virtual;
class function NewInstance: TObject; virtual;
procedure FreeInstance; virtual;
destructor Destroy; virtual;
end;
从 TObject 的声明中可以看到,TObject 包含了诸如实例初始化、实例析构、RTTI、消
息分发等相关实现的方法。现在就来研究一下 TObject 与消息分发,这也是 VCL 对 Windows
消息封装的模型基础。
在 TObject 类中,有一个 Dispatch()方法和一个 DefaultHandler()方法,它们都是与消息
分发机制相关的。
Dispatch()负责将特定的消息分发给合适的消息处理函数。首先它会在对象本身类型
的类中寻找该消息的处理函数,如果找到,则调用它;如果没有找到而该类覆盖了 TObject
的 DefaultHandler(),则调用该类的 DefaultHandler();如果两者都不存在,则继续在其基
类中寻找,直至寻找到 TObject 这一层,而 TObject 已经提供了默认的 DefaultHandler()
方法。
先来看一个示例程序,它演示了消息分发及处理的过程。该程序的代码及可执行文件
可在配书光盘的 MsgDisp 目录下找到。
首先自定义一个消息结构 TMyMsg,它是我们自定义的消息记录类型。对于自定义的
消息类型,VCL 只规定它的首 4 字节必须是消息编号,其后的数据类型任意。同时,VCL
也提供了一个 TMessage 类型用于传递消息。在此程序中,不使用 TMessage,而用 TMyMsg
代替:
·68·
Click to buy NOW!
P
D
F
-
X
C
h
a
n
g
e
V
i
e
w
e
r
w
w
w
.
d
o
c
u
-
t
r
a
c
k
.
c
o
m
Click to buy NOW!
P
D
F
-
X
C
h
a
n
g
e
V
i
e
w
e
r
w
w
w
.
d
o
c
u
-
t
r
a
c
k
.
c
o
m
VCL 库
4
type
TMyMsg = record // 自定义消息结构
Msg : Cardinal; // 首 4 字节必须是消息编号
MsgText : ShortString; // 消息的文字描述
end;
TMyMsg 记录类型的第 2 个域我们定义为 MsgText,由该域的字符串来给出对这个消
息的具体描述信息。当然,这些信息都是由消息分发者给出的。
然后,定义一个类,由它接受外界发送给它的消息。这个类可以说明这个演示程序的
核心问题。
TMsgAccepter = class // 消息接收器类
private
// 编号为 2000 的消息处理函数
procedure AcceptMsg2000(var msg : TMyMsg); message 2000;
// 编号为 2002 的消息处理函数
procedure AcceptMsg2002(var msg : TMyMsg); message 2002;
public
procedure DefaultHandler(var Message); override; //默认处理方法
end;
在 Object Pascal 中,指明类的某个方法为某一特定消息的处理函数,则在其后面添加
message 关键字与消息值,以此来通知编译器。正如上面类定义中的
procedure AcceptMsg2000(var msg : TMyMsg); message 2000;
指明 AcceptMsg2000()方法用来处理值为 2000 的消息,该消息以及参数将通过 msg 参数传
递给处理函数。
TMsgAccepter 类除提供了值为 2000 和 2002 的两个消息的处理函数外,还提供了一个
默认的消息处理方法 DefaultHandler()。该方法是在 TObject 中定义的虚方法,而在
TMsgAccepter 类中覆盖(override)了该方法,重新给出了新的实现。
TMyMsg 结构声明与 TMsgAccepter 类的声明与实现都被定义在 MsgDispTest 单元中。
完整的单元代码如下,请参看其中的 TMsgAccepter 类的各方法的实现:
unit MsgDispTest;
interface
uses Dialogs, Messages;
type
·69·
Click to buy NOW!
P
D
F
-
X
C
h
a
n
g
e
V
i
e
w
e
r
w
w
w
.
d
o
c
u
-
t
r
a
c
k
.
c
o
m
Click to buy NOW!
P
D
F
-
X
C
h
a
n
g
e
V
i
e
w
e
r
w
w
w
.
d
o
c
u
-
t
r
a
c
k
.
c
o
m
剩余56页未读,继续阅读
资源评论
EYUANatQQdotCOM
- 粉丝: 11
- 资源: 113
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功