VCL 控制項的視窗控制代碼 (Window Handle / HWND) 並非在建構子中建立,而是延遲到 CreateWnd 方法執行時。若需在 Handle 可用後立即執行動作 (如發送訊息、設定子類別化、呼叫需 HWND 的 API),正確做法是覆寫 CreateWnd 並在 inherited 之後撰寫程式碼。
type
TMyCustomControl = class(TCustomControl)
protected
procedure CreateWnd; override;
end;
procedure TMyCustomControl.CreateWnd;
begin
// 此時 Handle 尚未建立
inherited CreateWnd; // 呼叫基類建立 Handle
// 此時 Handle 已可用 (Self.Handle <> 0)
// 在此執行需 HWND 的初始化動作
// 例:SetWindowLong(Handle, GWL_STYLE, ...);
// 例:SendMessage(Handle, WM_SETFONT, Font.Handle, 0);
end;
CreateWindowEx 建立實際 HWND。HandleNeeded 屬性存取會觸發建立,但不保證父視窗鏈結完成。CreateWnd 是 VCL 統一的 Handle 建立進入點,確保父視窗、樣式、字型等前置條件就緒。
procedure TMyCustomControl.DestroyWnd;
begin
// Handle 即將銷毀,先清理相關資源
// 例:移除子類別化、釋放 Hook
inherited DestroyWnd; // 釋放 Handle
end;
SetWindowLong(Handle, GWL_WNDPROC, ...)) 需在 Handle 建立後、顯示前完成。DragAcceptFiles, RegisterHotKey, SetLayeredWindowAttributes 等。SetWindowRgn) 建立非矩形視窗。Canvas.Handle 繪圖初始化 (雖 TCanvas 已封裝此邏輯)。inherited CreateWnd,否則 Handle 永不建立,控制項不可見。CreateWnd 中存取會觸發 HandleNeeded 的屬性 (如 Left, Top),可能導致遞迴或重複建立。TWinControl 衍生類,CreateParams 可調整建立參數 (樣式、延伸樣式、類別名稱),CreateWnd 負責後續初始化。「覆寫 CreateWnd,inherited 後執行需 HWND 的邏輯」是 Delphi 元件開發的核心模式之一。掌握 Handle 生命週期 (CreateWnd → 可用 → DestroyWnd → 釋放) 並在此兩點掛鉤初始化/清理,是編寫穩健、相容性好的自訂控制項關鍵。