首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 元件開發:事件建立與訊息處理系統深度解析

     編輯:Delphi

19.2.2.2 建立事件

事件連結系統發生的動作與回應代碼(事件處理程序)。透過事件,應用程式開發者無需修改元件源碼即可客製化行為。

1. 事件的本質

① 事件即方法指標

Delphi 以方法指標實現事件——指向特定物件實例特定方法的指標。元件編寫者將其作為容器,事件觸發時呼叫使用者定義的方法:

procedure TControl.Click;
begin
  if Assigned(OnClick) then OnClick(Self);
end;

② 事件即屬性

事件以屬性形式實現,使用私有欄位儲存方法指標(慣例加 F 前綴),屬性型別為方法指標型別:

type
  TControl = class(TComponent)
  private
    FOnClick: TNotifyEvent;
  protected
    property OnClick: TNotifyEvent read FOnClick write FOnClick;
  end;

③ 事件處理程序型別

所有事件皆為程序。Delphi 定義標準型別(如 TNotifyEvent、TKeyPressEvent),自訂事件可復用或自行定義。若需回傳資訊,僅能透過 var 參數。典型範例 TKeyPressEvent 允許修改 Key 以改變字元或抑制預設處理。

④ 事件處理程序為可選

元件不得依賴使用者撰寫處理程序。空處理程序應與無處理程序產生相同結果。正確呼叫模式:

if Assigned(OnClick) then OnClick(Self);
{ 執行預設處理 }

錯誤模式:在 else 中執行預設處理,將導致使用者無法透過空處理程序抑制行為。

若需支援使用者覆寫預設行為(如 OnKeyPress 設 Key := #0 抑制字元),應在呼叫事件後檢查 var 參數:

if Assigned(OnKeyPress) then OnKeyPress(Self, Key);
if Key <> #0 then { 執行預設處理 };

2. 實現標準事件

所有控制項繼承自 TControl 的標準事件(OnClick、OnMouseDown 等)及 TWinControl 的鍵盤/焦點事件。這些事件在祖先類別中為 protected 動態方法,若需公開,只需在子類別 published 區重新宣告屬性名稱即可繼承實作:

type
  TMyControl = class(TCustomControl)
  published
    property OnClick; { 使其出現在物件檢視器 }
  end;

修改標準事件行為:覆寫對應動態方法(如 Click),呼叫 inherited 保留標準流程(含使用者事件處理),再加入自訂邏輯。

3. 定義自訂事件

僅當行為截然不同於現有事件時才需定義新事件。步驟:觸發條件 → 定義處理程序型別 → 宣告事件屬性 → 呼叫事件。觸發來源可能為 Windows 訊息、屬性變更或內部邏輯。範例展示 TControl 如何將 WM_LBUTTONDOWN 轉為 OnMouseDown 事件。

19.2.2.3 處理訊息

Delphi 以訊息分派系統將 Windows 訊息轉為物件方法呼叫。核心三層:MainWndProc(靜態、含例外處理)→ WndProc(虛擬、可覆寫過濾)→ Dispatch(靜態、依 Msg 欄位分派至對應處理方法或 DefaultHandler)。

1. 理解訊息處理系統

Windows 訊息結構

包含訊息 ID、wParam (16-bit)、lParam (32-bit) 及結果值。Delphi 為各類訊息定義專屬記錄型別(如滑鼠訊息的 XPos/YPos),避免手動拆解位元。

分派機制

每個元件類型註冊 MainWndProc 為視窗程序,轉交給 WndProc,再由 Dispatch 依訊息 ID 尋找處理方法。若無對應方法則呼叫 DefaultHandler(通常忽略)。此機制保證向任何元件發送任意訊息皆安全。

2. 修改訊息處理方法

原則:優先修改事件行為而非訊息行為。若必須修改,覆寫對應處理方法(使用 message 指令而非 override):

type
  TMyComponent = class(...)
    procedure WMPaint(var Message: TWMPaint); message WM_PAINT;
  end;

處理方法中可讀寫訊息記錄所有欄位(var 參數),常修改 Result 以改變回傳值。若需攔截訊息防止分派,覆寫 WndProc 於呼叫 inherited 前過濾:

procedure TMyControl.WndProc(var Message: TMessage);
begin
  if ShouldProcess(Message) then inherited WndProc(Message);
end;

TControl.WndProc 即示範拖曳時過濾滑鼠訊息的實作。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved