⑸ 缺省屬性值
當聲明一個屬性,能有選擇地聲明屬性的缺省值。部件屬性的缺省值是部件構造方法中的屬性值集。例如,當從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;