實踐第一步——分析和設計
Delphi為我們提供的組件中,有一個Label控件,它完成了最基本的單行文本標簽功能。不過它的功能實在是太有限啦,總是在那裡灰不溜秋地趴著。現在我們給它增加點動態效果,讓它成為一個可以在鼠標經過時改變外表的標簽——TouchLabel。也就是說,在Label的基礎上,我們要給它添加幾個屬性,使鼠標經過時,標簽的的文字效果會變為我們指定的樣子。那麼,我們要擴充的功能分為以下幾部分:
1、兩個屬性及其對應的屬性編輯器,為它指定MouseMoving時的背景色和前景色。
2、在鼠標經過標簽上時,改變標簽的外觀。
3、鼠標移出後,把外觀改為原來的樣子。
分析這三個功能,需要用到以下的技術:
自義屬性,事實上把屬性定義為Publish類型,並為它指定對應的Read和Write方法,它就會出現在屬性編輯器中。現在我們把這兩個屬性命名為TouchBKColor和TouchFont。現在看一下我的屬性定義:
property TouchBKColor : TColor Read GetTouchBKColor Write SetTouchBKColor
stored isStoreTouchBKColor default clWindow;
property TouchFont : TFont Read FTouchFont Write SetTouchFont
stored isStoreTouchFont;
stored是標識這個屬性是否要保存在程序的.dfm中以做持久化,通常它由一個返回值為 Boolean 類型的函數來控制。這裡是isStoreTouchBKColor 和isStoreTouchFont。而default是用來為這個屬性指定一個默認值。另外,我還定義了一個屬性來判斷是否需要讓這個Touch功能生效。就是
property ChangeWhileTouch : Boolean Read isStoreTouchFont
Write isStoreTouchFont default True;
這些代碼並不復雜,我直接將它們附在後面,在這裡就不多占篇幅了。只有兩點要指出,一個是在屬性本身的Read和Write方法中不可以對屬性本身進行讀寫,否則會引起無窮遞歸。還有一個是屬性本身不保存信息,通常的做法是在讀寫方法中操作某一私有字段。
“事件”響應,這不是平時我們所用的事件響應,而是為鼠標進出控件編寫對應的代碼。在VCL和CLX中,采用的是不同的方法。VCL的消息體系和Windows的消息體系比較接近,我們要找出鼠標進出控件的消息,寫對應的消息響應代碼。而CLX是基於著名的C++跨平台類庫QT開發的。所以它采用的是QT的信號——槽機制。好在CLX可視控件的基礎類TControl為我們封裝了MouseEnter和MouseLeave,我們只要重載這兩個成員方法,寫上我們自己的代碼。而在VCL和CLX的TouchLabel組件中,這些代碼完全通用。方法載很簡單,我介紹一下消息響應。
VCL的消息響應:
當然,我們先要找到鼠標出入控件的消息。別以為我這是廢話,Borland公司的技術資料之糟糕和他們出色的開發工具一樣舉世聞名,而這兩個消息又不是Windows的標准消息,所以我們要自己去找。告訴你一個秘密,VCL的消息列表在Controls單元中。我就是在那裡找到了CM_MOUSEENTER和CM_MOUSELEAVE消息。現在我們學習一下Delphi的消息響應方法的格式:
procedure procedureName(var Message: Tmessage); Message TheMessage;
procedure關鍵字說明消息響應是一個方法,procedureName是你為它起的名字,它的參數是可以先照抄,後面的TheMessage就是你要這個方法響應的消息。
所以,我們定義這兩個方法為
procedure TTouchLabel.CMMouseEnter(var Message: TMessage);
begin
inherited;
if not ChangeWhileTouch then exit;
if FColor %26lt;%26gt; FTouchColor then
begin
FTempColor := Color;
Color := TouchBKColor;
end;
FTempFont.Assign(Font);
Font.Assign(TouchFont);
end;
procedure TTouchLabel.CMMouseLeave(var Message: TMessage);
begin
inherited;
if not ChangeWhileTouch then exit;
if FColor %26lt;%26gt; FTouchColor then
Color := FTempColor;
Font.Assign(FTempFont);
end;
在CLX版本中,只是方法的聲明不同,實現代碼是一樣的,所以不多說了。最後要指出的是,這裡面我們會用到對象類型的成員,一定要記著自己定義,自己構造,自己析構。