發組件的過程,其實就是從某一對象派生出一個新的對象,並且為該對象聲明新的屬性、方法和事件。下面我將通過制作一個標題欄按鈕來講述如何制作組件。
標題欄按鈕組件TTitleBarButton以TComponent為直接繼承對象,它是一個可以在窗體標題欄上顯示按鈕的組件,像最大化、最小化和關閉按鈕等。最新的Winamp MP3播放器,它有一個插件可以在任何窗體上顯示一排播放按鈕,我想通過下面的技術也可以實現。
1、首性確定組件的屬性。屬性是組件的重要組成部分,它相當於組件的門面,因為一旦一個組件被置於窗體中時,用戶必然想到去設置組件的各種屬性,編寫各種事件的處理過程。TTitleBarButton有以下屬性:
Color:用來決定按鈕表面的顏色。
Glyph:用來決定按鈕表面的圖片。
PopupMenu:用來決定右鍵單擊按鈕時的彈出菜單。
RightMargin:用來確定按鈕的位置,以窗體右邊界為基准。
Visible:用來決定按鈕是否可見。
2、確定組件的方法。方法是組件的基本構成部分之一,在編寫方法時,盡量減少方法間的依賴關系,並確定方法的可見度,以及是否為虛函數等。在本例中,主要方法如下:
function GetBoundsRect: TRect; 用來確定按鈕的邊界矩形,可見度為private
procedure NewWndProc(var message: TMessage); 窗體的新的窗口過程,private
procedure Paint; virtual; 該類的繼承者可以override該方法,但用戶不能直接調該方法
procedure Repaint; 是Paint方法的對外接口,用戶可以調用此方法,以強制重新畫按鈕
3、確定組件的事件。事件實際上是一種特殊的屬性,它也是組件的很重要組成部分,事件為組件響應系統發生的行為而執行的一段代碼連接。事件就是方法指針,是方法的觸發器。TtitleBarButton只有一個事件:
OnClick事件,用來響應用戶的Click事件代碼。
另外,要減少組件的依賴關系。使一個組件在執行其代碼時所受的約束盡可能地少,這是開發組件的一個主要目標,它也是衡量一個組件性能好壞的重要標准之一。
實現標題欄按鈕需要解決以下主要問題:
1、 如何確定按鈕的邊界,即Left,Top,Width,Height
通過GetWindowRect來取得窗體的邊界矩形,通過GetSystemMetrics取得窗體的框架寬度和標題欄按鈕的高度、寬度。再加上RightMargin屬性就可以基本上確定按鈕的邊界了。
2、 如何畫按鈕的外觀(包括按下和凸起)
通過GetWindowDC來取得窗體DC(包括標題欄、菜單、滾動條等),我們就可以在這個DC上畫按鈕了。
3、 如何讓按鈕響應消息(比如Click,單擊右鍵彈出菜單等)
我們可以通過GetWindowLong取得窗體的窗口過程,然後把我們新定義的窗口過程通過SetWindowLong給這個窗體,然後我們在自己的窗口過程中來讓按鈕響應消息。
全部代碼如下:
unit TitleBarButton;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Menus, Dialogs;
type
TTitleBarButton = class(TComponent)
private
FColor: TColor;
FGlyph: TBitmap;
FForm: TCustomForm;
FOldWndProc: Pointer;
FButtonDown: Boolean;
FVisible: Boolean;
FRightMargin: Cardinal;
FPopup: TPopupMenu;
FOnClick: TNotifyEvent;
procedure SetGlyph(const Value: TBitmap);
procedure SetVisible(const Value: Boolean);
procedure SetRightMargin(const Value: Cardinal);
function GetBoundsRect: TRect;
procedure NewWndProc(var message: TMessage);
protected
procedure Notification(Component: TComponent;Operation: TOperation); override;
procedure Paint; virtual;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Repaint;
property BoundsRect: TRect read GetBoundsRect;
published
property Color: TColor read FColor write FColor default clBtnFace;
p
[1] [2] [3] [4] [5] [6] 下一頁