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

⑸ 缺省属性值

当声明一个属性,能有选择地声明属性的缺省值。部件属性的缺省值是部件构造方法中的属性值集。例如,当从Component Palette选择某部件置于窗体中时,Delphi通过调用部件构造方法创建部件,并决定部件属性初始值。

Delphi使用声明缺省值决定是否将属性值存在DFM文件中。如果不描述缺省值,Delphi将总是保存该属性值。声明缺省值的方法是在属性声明后加default指令,再跟缺省值。

当重声明一个属性时,能够描述没有缺省值的属性。如果继承的属性已有一个,则设立没有缺省值的属性的方法是在属性声明后加nodefault指令。如果是第一次声明属性,则没有必要加nodefault指令,因为没有default指令即表示如此。

下例是名为IsTrue的布尔类型属性设置缺省值True的过程:

type

TSampleComponent=class(TComponent)

private

FIsaTrue: Boolean;

pubilic

constructor Create (AOwner: TComponent); Overvide;

published

property Istrue: Boolean read FIsTrue write FIsTrue default True;

end;

constructor TSampleComponent.Create (AOwner: TComponent);

begin

inherited Create ( Aowner);

Fistvue := True; { 设置缺省值 }

end;

5. 编写属性编辑器

Object Inspector提供所有类型属性的缺省编辑器,Delphi也支持通过编写和注册属性编辑器的方法为属性设计自己的编辑器。可以注册专门为自定义部件的属性设计的编辑器,也可设计用于所有某类型的属性。编写属性编辑器需要下列五个步骤:

● 继承一个属性编辑器对象

● 将属性作为文本编辑

● 将属性作为整体编辑

● 描述编辑器属性

● 注册属性编辑器

⑴ 继承属性编辑器对象

DsgnIntf库单元中定义了几种属性编辑器。它们都是从TPropertyEditor继承而来。当创建属性编辑器时,可以直接从TPropertyEditor中继承或从表中的任一属性编辑器中继承。

表19.4 属性编辑器的类型

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

类型 编辑的属性

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

TOrdinalProperty 所有有序的属性(整数、字符、枚举)

TIntegerProperty 所有整型,包括子界类型

TCharProperty 字符类型或字符子集

TEnumProperty 任何枚举类型

TFloatProperty 所有浮点数

TStringProperty 字符串,包括定长的字符串

TSetElementProperty 集合中的独立元素

TSetElementProperty 所有的集合,并不是直接编辑集合类型,而是展开成一列

集合元素属性

TClassProperty 对象,显示对象名,并允许对象属性的展开

TMethodPropevty 方法指针,主要指事件

TComponentProperty 相同窗体中的部件,用户不能编辑部件的属性,

但能指向兼容的部件

TColorProperty 部件颜色,显示颜色常量,否则显示十六进制数

TFontNameProperty 字体名称

TFontProperty 字体,允许展开字体的属性或弹出字体对话框

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

下面是TFloatPropertyEditor的定义:

type

TFloatProperty=Class(TPropertyEditor)

public

function AllEqual: Boolean; override;

function GetValue: String; override;

procedure SetValue ( Const Value: string ); override;

end;

⑵ 象文本一样编辑属性

所有的属性都需要将它们的值在Object Inspector窗口中以文本的方式显示。属性编辑器对象提供了文本表现和实际值之间转换的虚方法。这些虚方法是GetValue和SetValue,你的属性编辑器也能继承了一系列的方法用于读和写不同类型的值。见下表:

表19.5 读写属性值的方法

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

属性类型 "Get"方法 "Set"方法

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

浮点数 GetFloatValue SetFloatVallue

方法指针 GetMethodValue SetMehodValue

有序类型 GetOrdValue SetOrdValue

字符串 GetStrValue SetStrValue

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

当覆盖GetValue方法时,调用一个"Get"方法;当覆盖SetValue方法时调用一个"Set"方法。

属性编辑器的GetValue方法返回一个字符串以表现当前属性值。缺省情况下GetValue返回"unknown"。

属性编辑器的SetValue接收Object Inspector窗口String类型的参数,并将其转换成合适的类型,并设置属性值。

下面是TIntegerProperty的GetValue和SetValue的例子:

function TIntegerProperty GetValue: string;

begin

Result := IntToStr (GetOrdValue);

end;

proceduve TIntegerPropertySetValue (Const Value: string);

var

L: Longint;

begin

L := StrToInt(Value); { 将字符串转换为数学 }

with GetTypeData (GetPropType)^ do

if ( L < Minvalue ) or ( L > MaxValue ) then

Raise EPropertyError.Create (FmtloadStr(SOutOfRange,

[MinValue,MaxValue]));

SetOrdValue (L);

end;

⑶ 将属性作为一个整体来编辑

Delphi支持提供用户以对话框的方式可视化地编辑属性。这种情况常用于对对象类型属性的编辑。一个典型的例子是Font属性,用户可以找开Font对话框来选择字体的属性。

提供整体属性编辑对话框,要覆盖属性编辑对象的Edit方法。Edit方法也使用"Get"和"Set"方法。

在大多数部件中使用的Color属性将标准的Windows颜色对话框作为属性编辑器。下面是TColorProperty的Edit方法

procedure TColorProperty.Edit

var

ColorDialog: TColorDialog;

begin

ColorDialog := TColorDialog.Create(Application); { 创建编辑器 }

try

ColorDialog.Color := GetOrdValue; { 使用已有的值 }

if ColorDialog.Execute then

SetOrdValue (ColorDialog.Color);

finally

ColorDialog.Free;

end;

end;

⑷ 描述编辑器的属性

属性编辑必须告诉Object Inspector窗口如何采用合适的显示工具。例如Object Inspector窗口需要知道属性是否有子属性,或者是否能显示可能取值的列表。描述编辑器的属性通常覆盖属性编辑器的GetAttributes方法。

GetAttributes返回TPropertyAttributes类型的集合。集合中包括表中任何或所有的值:

表19.6 属性编辑器特征标志

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

标志 含 义 相关方法

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

paValuelist 编辑器能给予一组枚举值 GetValues

paSubPropertie 属性有子属性 GetPropertises

paDialog 编辑器能显示编辑对话框 Edit

PaMultiSelect 当用户选择多于一个部件

时,属性应能显示 N/A

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

Color属性是灵活的,它允许在Object Inspector窗口中以多种方式选择他们。或者键入,或者从列表中选择定编辑器。因此TColorProperty的GetAttributes方法在返回值中包含多种属性。

function TColorProperty.GetAttributes: TProrertyAttributes;

begin

Result := [PaMultiselect, paDialog, paValuelist];

end;

⑸ 注册属性编辑器

一旦创建属性编辑器,必须在Delphi中注册。注册属性编辑器时,要与某种属性相联。

调用RegisterPropertyEditor过程来注册属性编辑器。该过程接受四个参数:

● 要编辑的属性的类型信息的指针。这总是通过调用调用TypeInfo函数得到,如TypeInfo ( TMyComponent )

● 编辑器应用的部件类型,如果该参数为nil则编辑器应用于所给的类型的所有属性

● 属性名,该参数只有在前一参数描述了部件的情况下才可用

● 使用该属性编辑器的属性的类型

下面引用了注册标准部件的过程:

procedure Register;

begin

RegisterPropertyEditor (TypeInfo(TComponent), nil, TComponentProperty,

RegisterPropertyEditor(TypeInfo(TComponentName), TComponent,

'Name', (ComponentNamePropety);

RegisterPropertyEditor (TypeInfo(TMenuItem), TMenu, '', TMenuItemProperty);

end;

时间: 2024-11-08 21:19:42

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

第十九章-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自定义部件开发(一)(3)

19.2.1.5 编写部件的面向对象技术 部件使用者在Delphi环境中开发,将遇到在包含数据和方法的对象.他们将在设计阶段和运行阶段操作对象,而编写部件将比他们需要更多的关于对象的知识,因此,你应当熟悉Delphi的面向对象的程序设计. 1. 建立部件 部件用户和部件编写者最基本的区别是用户处理对象的实例,而编写者创建新的对象类型.这个概念是面向对象程序设计的基础.例如,用户创建了一个包含两个按钮的窗体,一个标为OK,另一个标为Cancel,每个都是TButton的实例,通过给Text.def

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

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

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

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