(接上文)
四、組件屬性編輯器和組件編輯器:
通過上面的努力我們的組件似乎已經比較完美了,可我們也忽略了一些重要的細節和一些有趣的事情,這一篇我們將研究兩個很有用的組件特性:
在之前開發組件核心功能時我們曾設置了兩個屬性BeginTime和WakeTime,他們都是字符串型的屬性,然而他們所要表示的卻是時間類型,這樣就很有可能使組件使用者錯誤的編輯屬性並導致轉化字符串到時間時出錯(當然這裡只是為了文章的講解,我們故意把它設置為了字符串類型),雖然通過浏覽原代碼你知道我們也做了一些代碼級別的防出錯處理,使當輸入錯誤時屬性自動變成‘00:00:00’,然而這對組件使用者來講仍然顯的很不友好,所以我們需要為這兩個屬性定制編輯器,我們的編輯器將彈出一個窗口裡面有一個TdateTimePicker用來選擇時間。在delphi中有許多這樣的例子,例如大家都知道的lines屬性,當你單擊它右放的省略號時為自動彈出一個文本編輯器來編輯lines,這大大降低了組件使用者范錯誤的可能性。
在定制完屬性編輯器以後,我們將為組件本身加入一寫有趣的元素——組件編輯器,這也是在delphi中經常出現的,例如有些組件當你雙擊它時,它並不會進入代碼編寫狀態,而是彈出它自己的編輯器。雖然我們的組件似乎並不需要這種特性,但為了演示它,我們也將它考慮近來,我們給我們的組件編寫了一個版權信息和一個關於對話框,當組件使用者雙擊它時彈出關於信息(當然,這僅僅是種演示)。上面提到的兩種特性由於它們只是會在設計時起作用,所以你完全可以在新的組件包中編寫並注冊它們,並將這個組件包設置為Designtime Only,為了方便起見我們就直接把它們和組件的單元編寫在一起。注意:以下出現的一些類和方法都需要引用單元DesignEditors(delphi7)或DsgnIntf(delphi5),與前面說的一樣,它們都屬於delphi的open tools api所以,如果你沒有這寫單元請按照前文的方法安裝它們。
首先來編寫屬性編輯器,由於BeginTime和WakeTime是字符串類型,所以我們必須從默認的字符串屬性編輯器類TstringProperty繼承並覆蓋它的一寫方法(這裡只介紹幾個重要的方法,事實上所有的屬性編輯器都從TpropertyEditor繼承而來,然而我們不用直接繼承這個基類)。其中一個重要的方法是GetAttributes,他將返回一些代表編輯器功能的值,這些值將會在代碼的注釋中說明(如果你的屬性編輯器還需要一個下拉列表,你還需要另外一個重要的方法GetValues具體請查看delphi幫助)另外為了使屬性編輯器為彈出的對話框我們需要覆蓋Edit方法。為了可以以可視化的方式設計對話框,我們可以建立一個普通工程,在設計好後將窗體的類聲明復制到我們的組件單元,並將窗體的dfm文件拷貝到我們的組件包目錄,並在代碼中加入編譯器開關{$R *.dfm}。以下是窗體的類聲明,這個窗體沒有任何的代碼需要編寫:
TTimeEditFrm = class(TForm)
DateTimePicker1: TDateTimePicker;
Button1: TButton;
Button2: TButton;
private
{ Private declarations }
public
{ Public declarations }
end;
以下是屬性編輯器的代碼:
TClockProperty=class(TStringProperty)
public
function GetAttributes:TPropertyAttributes;override;
procedure Edit;override;
end;
實現部分:
procedure TClockProperty.Edit;
var
TimeEditFrm:TTimeEditFrm;
begin
TimeEditFrm:=TTimeEditFrm.Create(Application);
try
TimeEditFrm.DateTimePicker1.Time:=StrToTime(GetValue);
if TimeEditFrm.ShowModal=mrOK then
SetValue(TimeToStr(TimeEditFrm.DateTimePicker1.Time));
//GetValue和SetValue是TStringProperty的基類方法,他直接讀取和設置字符串的值
finally
TimeEditFrm.Free;
end;
end;
function TClockProperty.GetAttributes: TPropertyAttributes;
begin
result:=[paDialog,paMultiselect];
//paDialog表示屬性編輯器將顯示一個對話框,paMulitiselect允許多個組件選擇屬性
//除此之外如果你想讓屬性編輯器顯示下拉列表,你還需要paValueList具體請查看幫助
end;
最後我們用RegisterPropertyEditor方法注冊屬性編輯器:
procedure Register;
begin
……
RegisterPropertyEditor(TypeInfo(string),TClock,BeginTime,TClockProperty);
RegisterPropertyEditor(TypeInfo(string),TClock,WakeTime,TClockProperty);
end;
重新編譯更新組件後我們就可以測試了.
接下來我們來實現組件編輯器:
組件編輯器需要繼承TcomponentEditor並覆蓋一些重要的方法,GetVerbCount返回設計時組件右鍵自定義菜單的數目,GetVerb為每一個自定義菜單添加文字,ExecuteVerb為每一個菜單項添加事件,Edit為組件的缺省操作指定事件(即在設計時雙擊組件),以下是代碼:
TClockEditor=class(TComponentEditor)
public
function GetVerbCount:integer;override;
function GetVerb(index:integer):string;override;
procedure ExecuteVerb(index:integer);override;
procedure Edit;override;
end;
實現部分:
procedure TClockEditor.Edit;
begin
ExecuteVerb(1); //默認顯示關於
end;
procedure TClockEditor.ExecuteVerb(index: integer);
begin
case index of
//第一個顯示名字的菜單什麼都不做顯示
1:showmessage(hk.barton@2003);
end;
end;
function TClockEditor.GetVerb(index: integer): string;
begin
case index of
0:result:=hk.barton;
1:result:=About Clock;
end;
end;
function TClockEditor.GetVerbCount: integer;
begin
result:=2;//我們顯示兩條菜單,一個我的名字,一個關於
end;
同樣最後我們注冊組件編輯器:
procedure Register;
begin
……
RegisterComponentEditor(TClock,TClockEditor);
end;
文章寫到這裡也該結束了,雖然寫了那麼多,然而在組件開發中這仍是一小部分內容,本文只是拋磚引玉的作用,希望對正要進入組件開發的朋友一些啟示。為了方便你閱讀本文,如果你想要本文所開發的這個組件的全部原文件,請和我聯系:
E-mail:[email protected] [email protected] QQ:6813489
(全文完)
參考文獻:
Marco Cantu 《Mastering Delphi》