可視化控件(Visual Component)實際上就是一個類(class)
要編寫一個類
可以直接在*
pas文件中編寫
但是要編寫控件
則必須使用包(package)
從File菜單中選擇New
新建一個Package
這就是存放和安裝控件用的包
然後單擊Package窗口中的Add按鈕
添加一個元件(Unit)
在彈出的對話框最上方選擇New Component因為一個控件的所有屬性方法事件不可能都由自己編所以就需要選擇祖先類(或者叫做父類或基類)然後再在其上面添加自己的屬性方法事件在Ancestor type後的下拉框中選擇所需的祖先類由於編寫可視化控件必須要畫圖所以選擇TGraphicControl作為祖先類再在Class Name框中輸入新控件(類)的名稱一般以T開頭Palette Page是用來選擇新控件在Delphi的窗口中的控件頁面名稱例如Standard 這個可以自己取在Unit File Name中添好新控件文件的路徑及文件名單擊OK按鈕新的控件便加入了現在可以為該控件編寫代碼了
下面以編寫一個可以自定義圖片的滾動條為例說明編寫可視化控件的方法
按照上面的方法選擇TGraphicControl為祖先類新控件的名稱是TPigHorizontalScroller (小豬水平滾動條)選擇好文件路徑和文件名後單擊OK按鈕開始編寫代碼
每一個控件都會被創建(Create)和刪除(Destroy)所以必須首先編寫這兩個過程對於控件中的每一個過程都必須在前面先定義然後再在後面編寫
定義的過程或屬性有三種
(1)在private後定義的是屬於控件內部使用的使用該控件的人無法看到
(2)在protected後定義的一般是看不到的只在別人使用該控件作為祖先類編寫其它控件時才可見
(3)在public後定義的只允許別人在程序中調用
(4)在published後定義的可以在屬性窗口(Object Inspector)中看到由於創建和刪除過程除了在編程過程中建立控件時自動執行外還可能在程序運行過程中動態創建控件時被調用所以把它定義在public後⑴(該序號表示次步驟在所附源程序中的代碼的位置下同)現在也許還不知到應該在這兩個過程中編寫什麼如何去編我們在下面將會講到
我們首先為這個控件添加一些屬性我們定義一個Max屬性用於設置或讀取滾動條的最大值因為在程序中一般不直接使用屬性所以要定義一個變量和該屬性對應起來一邊修改或讀取其值因為它只在控件內部使用所以我們把它定義在private後⑵(一般與屬性相關聯的變量都以F開頭例如FMax)定義好變量後再定義屬性這個屬性需要再Object Inspector窗口中可見所以把它定義再published後⑶定義的語法是
property <屬性名>:<類型> read <讀取該屬性時對應的變量> write <寫入該屬性時對應的變量或過程>
其它的變量和屬性也類似的定義(例如Min最小值Value當前值等)下面我們定義幾個屬性和變量用於設置滾動條的圖片(因為圖片變量比較特殊所以單獨講一下)我們把LeftButtonUpPicture(向左按鈕圖片)LeftButtonDownPicture(向左按鈕按下圖片)等定義為TBitmap類型(一定要定義相對應的變量)
大家一定注意到了在所附的源程序中定義這幾個屬性時read後所指定的讀取屬性時對應的變量是F…而write後指定的寫入該屬性時對應的不是一個變量而是一個Set…之類的東西這是一個自定義的過程作為該功能的過程的定義為
procedure <過程名>(Value: <被設置的屬性的值的類型>)
因為執行寫入該類屬性的時候需要做其它的事情所以不能光用一個變量來處理應該用一個過程來處理這中過程一般定義在protected後在該類過程中使用一個在⑷處這樣一個語句來給TBitmap類型的變量來賦值這是由於該類型的變量不能直接賦值而采用的
定義完這些TBitmap類型的變量的屬性後上面講的create過程和destroy過程中就需要編寫代碼了因為TBitmap也是一個類所以在create過程中必須創建⑸在destroy過程中必須釋放掉(free)⑹這裡⑺所指的inherited語句是用於指明該過程是從祖先類類中繼承來的(這個一定不能掉)
因為我們編寫的是可視化控件所以必須在控件上畫圖我們這個控件的祖先類TGraphicControl中封裝有一個Canvas(畫布)對象我們可以直接使用它來畫圖如果你對畫布的使用還不太熟悉最好去找一本書來看一看
下面要做的工作就是畫圖了如何在控件上畫圖呢?祖先類TGraphicControl中有一個Paint事件當控件需要重畫時便會自動觸發我們現在要做的就是要為這個事件編寫一段程序首先在protected後定義一個Canvas對象由於它是祖先類中已有的所以不需要加任何說明⑻我們將使用這個對象來畫圖接著就要定義一個Paint過程編寫繪制控件的代碼先在public後定義Paint過程由於它是由祖先類觸發的而不是由用戶調用的所以後面必須加上override否則該控件將會由於Paint過程永遠不會被調用而不成為可視化控件⑼下面我們就來編寫Paint過程的代碼⑽
該文章所附的源程序的Paint過程中的T_Height等變量是用來保存滾動條中按鈕滑塊等的大小的這部分程序和普通的Application中的程序差別不大大部分都是對畫布進行操作相信大家一看就明白值得注意的是下面對FAutoSize變量的判斷⑾FAutoSize是和該控件的屬性AutoSize相關聯的布爾型變量是用來設置這個控件的大小是否隨圖片的大小而變化的注意在控件的代碼中一般都不直接調用屬性而是使用與其相對應的的變量
程序編到這裡就算是終於給自己的新控件做了一個外型了不過它還不能滾動現在我們來編寫鼠標事件讓我們能夠操縱它鼠標事件的過程的定義和Paint過程很相似只是後面要加上參數說明⑿鼠標事件分為MouseDownMouseMove和MouseUp三個在定義後面都要加上override接下來在後面編寫它的代碼注意這裡的鼠標事件是Mouse…而不是通常的OnMouse…可是在⒀處的定義是干什麼用的呢?這裡的事件定義都是給用戶使用的也就是說當使用該控件時會在Object Inspector中的Event頁面中顯示出來
這些鼠標事件的代碼也非常簡單判斷鼠標的坐標在畫布上畫出相應的圖片等並同時觸發相應的事件值得注意的是在調用自定義事件時都要先用⒁處的這樣一個語句來判斷用戶是否已經為該事件編寫代碼這一點非常重要否則會調用出錯
大家注意到了剛才所調用的事件都是自定義的定義的方法也很簡單和定義屬性差不多只是類型時TNotifyEvent罷了
TNotifyEvent是默認事件其定義為
TNotifyEvent = procedure(Sender: TObject)
如果你要定義另外形式的事件就必須這樣先在type後編寫
<事件類型名稱> = procedure(<參?gt;:<類型>)
例如
TCustomEvent = procedure(a: Integer; b:String);
然後在public後定義
<事件名稱>:<事件類型名稱>
例如
AnEvent: TCustomEvent;
看完這些這整個程序你應該理解了吧如果編譯或運行出錯注意檢查以下幾點
(1)create和destroy過程中是否有inherited語句
(2)TBitmap類型的變量create和free了沒有
(3)過程前有沒有控件名例如TPigHorizontalScrollerMoseMove
判斷鼠標是否進入或離開控件的方法
定義如下的過程
procedure MouseEnter(var Msg: TMessage); message CM_MOUSEENTER;
procedure MouseLeave(var Msg: TMessage); message CM_MOUSELEAVE;
再在下面編寫代碼就行了這個方法用於編寫三態按鈕很有用
From:http://tw.wingwit.com/Article/program/Delphi/201311/8448.html