動手寫元件前,必須建立正確的理論模型。本文系統梳理 VCL元件繼承體系、屬性本質與分類、事件代理機制、以及標準化開發四步驟,為後續實戰奠基。
TComponent (非可視元件基底)
├─ 非可視元件:TTimer, TTable, TOpenDialog, TDataSource...
└─ TControl (可視元件基底,引入 Left/Top/Width/Height/Visible 等)
├─ TGraphicControl (圖形控件,無視窗句柄,不佔系統資源)
│ └─ TLabel, TBevel, TShape...
└─ TWinControl (視窗控件,擁有 HWND,可獲焦點、接收訊息)
├─ TCustomControl (自繪視窗控件)
├─ TButton, TEdit, TListBox... (標準控件封裝)
└─ TCustomPanel → TPanel (容器控件)
選擇原則: 非可視→TComponent;純繪圖無互動→TGraphicControl;需焦點/訊息/子控件→TWinControl;容器/面板→TCustomPanel。
type
TSample = class
private
FCount: Integer;
procedure SetCount(Value: Integer);
published
property Count: Integer read FCount write SetCount default 0;
end;
procedure TSample.SetCount(Value: Integer);
begin
if FCount <> Value then FCount := Value; // 守護:避免重複賦值、觸發更新
end;
屬性分類與 Object Inspector 呈現:
| 類型 | 定義範例 | OI 呈現 |
|---|---|---|
| 簡單型別 | property Text: string read FText write SetText; | 編輯框 |
| 列舉型別 | property Align: TAlign read FAlign write SetAlign; | 下拉清單 |
| 集合型別 | property BorderIcons: TBorderIcons read FBorderIcons write FBorderIcons; | 多選勾選框 |
| 物件型別 | property Font: TFont read FFont write SetFont; | 可展開子屬性(需繼承 TPersistent) |
| 陣列型別 | property Selected[Index: Integer]: Boolean read GetSelected write SetSelected; | 需自訂屬性編輯器 |
default vs nodefault: default 0 表示「值為 0 時不存入 DFM」;nodefault 強制存入。真正的預設值需在 Create 中指派。
事件本質是方法指標(of object),指向外部處理程序。機制三步驟:
type TMouseEvent = procedure(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer) of object;FOnMouseDown: TMouseEvent;property OnMouseDown: TMouseEvent read FOnMouseDown write FOnMouseDown;觸發鏈路: 視窗程序捕獲 WM_LBUTTONDOWN → WMLButtonDown → DoMouseDown(座標轉換、保護判斷) → MouseDown → if Assigned(FOnMouseDown) then FOnMouseDown(Self, ...);
使用者指派 MyControl.OnMouseDown := MyHandler; 即完成代理連結。調度方法(DoXxx) 統一處理參數轉換與安全檢查,是 VCL 事件模式的關鍵設計。
Component → New Component 產生樣板與 Registerdclusr.dpk 或自訂).dcr 圖示(24×24,名稱 = 大寫類別名)TPropertyEditor)與元件編輯器(TComponentEditor)IDesigner、IOTAModule)TDataLink、TFieldDataLink)掌握上述核心觀念,元件開發不再是「照著抄」,而是「心中有架構、手下有章法」。