第十九章-Delphi自定义部件开发(一)(3)

19.2.1.5 编写部件的面向对象技术

部件使用者在Delphi环境中开发,将遇到在包含数据和方法的对象。他们将在设计阶段和运行阶段操作对象,而编写部件将比他们需要更多的关于对象的知识,因此,你应当熟悉Delphi的面向对象的程序设计。

1. 建立部件

部件用户和部件编写者最基本的区别是用户处理对象的实例,而编写者创建新的对象类型。这个概念是面向对象程序设计的基础。例如,用户创建了一个包含两个按钮的窗体,一个标为OK,另一个标为Cancel,每个都是TButton的实例,通过给Text、default和Cancel等属性赋不同的值,给OnClick事件赋予不同的处理过程,用户产生了两个不同的实例。

建立新部件一般有两个理由

● 改变类型的缺省情况,避免反复

● 为部件增加新的功能

目的都是为了建立可重用对象。如果从将来重用的角度预先计划和设计,能节省一大堆将来的工作。

在程序设计中,避免不必要的重复是很重要的。如果发现在代码中一遍又一遍重写相同的行,就应当考虑将代码放在子过程或函数中,或干脆建立一个函数库。

设计部件也是这个道理,如果总是改变相同的属性或相同的方法调用,那应创建新部件。

创建新部件的另一个原因是想给已有的部件增加新的功能。你可以从已有部件直接继承(如ListBox)或从抽象对象类型继承(如TComponent,TControl)。你虽然能为部件增加新功能,但不能将原有部件的属性移走,如果要这样做的话,就从该父对象的祖先对象继承。

2. 控制部件的访向

Object Pascal语言为对象的各部分提供了四个级别的访问控制。访问控制让你定义什么代码能访问对象的哪一部分。通过描述访问级别,定义了部件的接口。如果合理安排接口,将提高部件的可用性和重用性。

除非特地描述,否则加在对象里的域、方法和属性的控制级别是published,这意味着任何代码可以访问整个对象。

下表列出各保护级别:

表19.2 对象定义中的保护级别

━━━━━━━━━━━━━━━━━━━

保护级 用处

───────────────────

private 隐藏实现细节

protected 定义开发者接口

public 定义运行时接口

published 定义设计时接口

━━━━━━━━━━━━━━━━━━━

所有的保护级都在单元级起作用。如果对象的某一部分在库单元中的一处可访向,则在该库单元任意处都可访向。

⑴ 隐藏实现细节

如果对象的某部分被声明为private,将使其它库单元的代码无法访问该部分,但包含声明的库单元中的代码可以访问,就好象访问public一样,这是和C++不同的。

对象类型的private部分对于隐藏详细实现是很重要的。既然对象的用户不能访问,private部分,你就能改变对象的实现而不影响用户代码。

下面是一个演示防止用户访问private域的例子:

unit HideInfo;

interface

uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms,

Dialogs;

type

TSecretForm = class(TForm) { 声明新的窗体窗口 }

procedure FormCreate(Sender: TObject);

private { declare private part }

FSecretCode: Integer; { 声明private域 }

end;

var

SecretForm: TSecretForm;

implementation

procedure TSecretForm.FormCreate(Sender: TObject);

begin

FSecretCode := 42;

end;

end.

unit TestHide; { 这是主窗体库单元 }

interface

uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms,

Dialogs, HideInfo; { 使用带TSecretForm声明的库单元 }

type

TTestForm = class(TForm)

procedure FormCreate(Sender: TObject);

end;

var

TestForm: TTestForm;

implementation

procedure TTestForm.FormCreate(Sender: TObject);

begin

SecretForm.FSecretCode := 13; {编译过程将以"Field identifier expected"错误停止}

end;

end.

⑵ 定义开发者接口

将对象某部分声明为protected,可使在包含该部件声明的库单元之外的代码无法访问,就象private部分。protected部分的不同之处是,某对象继承该对象,则包含新对象的库单元可以访问protected部分,你能使用protected声明定义开发者的接口。也就是说。对象的用户不能访向protected部分,但开发者通过继承就可能做到,这意味着你能通过protected部分的可访问性使部件编写者改变对象工作方式,而又不使用户见到这些细节。

⑶ 定义运行时接口

将对象的某一部分定义为public可使任何代码访问该部分。如果你没有对域方法或属性加以private、protected、public的访问控制描述。那么该部分就是published。

因为对象的public部分可在运行时为任何代码访问,因此对象的public部分被称为运行接口。运行时接口对那些在设计时没有意义的项目,如依靠运行时信息的和只读的属性,是很有用的。那些设计用来供用户调用的方法也应放在运行时接口中。

下例是一个显示两个定义在运行时接口的只读属性的例子:

type

TSampleComponent = class(TComponent)

private

FTempCelsius: Integer; { 具体实现是private }

function GetTempFahrenheit: Integer;

public

property TempCelsius: Integer read FTempCelsius; { 属性是public }

property TempFahrenheit: Integer read GetTempFahrenheit;

end;

function GetTempFahrenheit: Integer;

begin

Result := FTempCelsius * 9 div 5 + 32;

end;

时间: 2025-01-31 02:01:19

第十九章-Delphi自定义部件开发(一)(3)的相关文章

第十九章-Delphi自定义部件开发(一)(1)

Delphi除了支持使用可视化部件所见即所得地建立应用程序外,还支持为开发应用而设计自己的部件. 在本章中将阐述如何为Delphi应用程序编写部件.这一章将达到两个目的: ● 教你如何自定义部件 ● 使你的部件成为Delphi环境的有机组合部分 19.1 Delphi部件原理 19.1.1 什么是部件 部件是Delphi应用程序的程序构件.尽管大多数部件代表用户界面的可见元素,但部件也可以是程序中的不可见元素,如数据库部件.为弄清什么是部件可以从三个方面来考察它:功能定义.技术定义和经验定义.

第十九章-Delphi自定义部件开发(三)(3)

编译过的Help文件和关键词文件应当与库单元在同一目录. ① 建立Help文件 你可以使用任何的工具创建Windows Help文件.Delphi的多文件搜索引擎,可以包含任何数目的Help文件的要素.在编译的Help文件之外,你应当拥有RTF源文件,这样才能生成关键词文件. 为使自定义部件的Help同库中其它部件一起工作,要遵循下列约定: ● 每个部件有占一页的帮助 部件帮助页应当给出部件目的的简单描述,然后列出最终用户可用的属性.事件和方法的描述.应用开发者通过在窗体上选择部件并按F1访问这

第十九章-Delphi自定义部件开发(三)(2)

19.2.2.4 注册部件 编写部件及其属性.方法和事件只是部件创建过程的一部分.尽管部件具有这些特征就可用,但部件真正功能强大的是在设计时操作它们的能力. 使部件在设计时可用需要经过如下几步: ● 用Delphi注册部件 ● 增加选择板位图 ● 提供有关属性和事件的帮助 ● 存贮和读取属性 1. 用Delphi注册部件 为了让Delphi识别自定义部件,并将它们放置于Component Palette上,你必须注册每一个部件. 注册一个部件要在部件所在单元里加入Register方法,这包括两个

第十九章-Delphi自定义部件开发(三)(1)

3. 创建新的消息处理方法 因为Delphi只为大多数普通Windows消息提供了处理方法,所以当你定义自己的消息时,就要创建新的消息处理方法. 用户自定义消息的过程包括两个方面: ● 定义自己的消息 ● 声明新的消息处理方法 ⑴ 定义自己的消息 许多标准部件为了内部使用定义了消息.定义消息的最一般的动因是广播信息和状态改变的通知. 定义消息过程分两步: ● 声明消息标识符 ● 声明消息记录类型 ① 声明消息标识 消息标识是整型大小的常量.Windows保存了小于1024的消息用于自己使用,因此

第十九章-Delphi自定义部件开发(二)(4)

⑵ 定义处理过程类型 一旦你决定产生事件,就要定义事件如何被处理,这就是要决定事件处理过程的类型.在大多数情况下,定义的事件处理过程的类型是简单的通知类型(TNotifyEvent)和已定义的事件类型. 通知事件只是告诉你特定的事件发生了,而没有描述什么时候和什么地方.通知事件使用时只带一个TObject类型的参数,该参数是Sender.然而所有通知事件的处理过程都知道是什么样的事件发生和发生在那个部件.例如:Click事件是通知类型.当编写Click事件的处理过程时,你知道的是Click事件发

第十九章-Delphi自定义部件开发(二)(3)

这三句表达式使用RegisterPropertyEditor三种不同的用法: ● 第一种最典型 它注册了用于所有TComponent类型属性的属性编辑器TComponentProperty.通常,当为某种类型属性注册属性编辑器时,它就能应用于所有这种类型的属性,因此,第二和第三个参数为nil. ● 第二个表达式注册特定类型的属性编辑器 它为特定部件的特定属性注册属性编辑器,在这种情况下,编辑器用于所有部件的Name属性. ● 第三个表达式介于第一个和第二个表达式之间 它为部件TMenu的TMen

第十九章-Delphi自定义部件开发(二)(2)

⑸ 缺省属性值 当声明一个属性,能有选择地声明属性的缺省值.部件属性的缺省值是部件构造方法中的属性值集.例如,当从Component Palette选择某部件置于窗体中时,Delphi通过调用部件构造方法创建部件,并决定部件属性初始值. Delphi使用声明缺省值决定是否将属性值存在DFM文件中.如果不描述缺省值,Delphi将总是保存该属性值.声明缺省值的方法是在属性声明后加default指令,再跟缺省值. 当重声明一个属性时,能够描述没有缺省值的属性.如果继承的属性已有一个,则设立没有缺省值

第十九章-Delphi自定义部件开发(一)(2)

2. 建立原始控制 标准控制是在运行时可见的.这些标准控制都从TWinControl,继承来的,当你建立原始控制时,你使用TCustomControl作为起始点.标准控制的关键特征是它具有窗口句柄,句柄保存在属性Handle中,这种控制: ● 能接受输入焦点 ● 能将句柄传送给Windows API函数 如果控制不需要接受输入焦点,你可把它做成图形控制,这可能节省系统资源. 3. 建立图形控制 图形控制非常类似定制的控制,但它们没有窗口句柄,因此不占有系统资源.对图形控制最大的限制是它们不能接收

第十九章-Delphi自定义部件开发(二)(1)

19.2.2 Delphi部件编程 19.2.2.1 创建属性 属性(Property)是部件中最特殊的部分,主要因为部件用户在设计时可以看见和操作它们,并且在交互过程中能立即得到返回结果.属性也很重要,因为如果将它们设计好后,将使用户更容易地使用,自己维护起来也很容易. 为了使你在部件中更好地使用属性,本部分将介绍下列内容: ● 为什么要创建属性 ● 属性的种类 ● 公布(publishing)继承的属性 ● 定义部件属性 ● 编写属性编辑器 1. 为什么要创建属性 属性提供非常重要的好处,最