C++Builder 的事件機制本質是「閉包指標」,將 Windows 訊息封裝為元件層級的可視化事件。本文完整示範如何定義自訂訊息 WM_MYMESSAGE、宣告事件型別 TMyEvent、建立觸發虛擬函式 DoMyEvent,並透過 __published 區塊讓事件出現在「物件檢視器」中,達到與 VCL 內建事件一致的開發體驗。
Windows 訊息 (WM_MYMESSAGE)
│
▼
WndProc 攔截 → DoMyEvent() 虛擬函式
│
▼
FOnMyEvent 閉包指標 (TMyEvent)
│
▼
使用者在 Object Inspector 雙擊撰寫事件處理常式
#define WM_MYMESSAGE (WM_USER + 100)
// 事件型別:__closure 關鍵字產生閉包(物件指標+成員函式指標)
typedef void __fastcall (__closure *TMyEvent)(TObject* Sender, int Param1, int Param2);
class TMyControl : public TWinControl {
private:
TMyEvent FOnMyEvent;
void __fastcall DoSomething(TMessage &Msg); // 訊息處理常式
virtual void __fastcall DoMyEvent(int P1, int P2); // 觸發事件的虛擬函式
protected:
virtual void __fastcall WndProc(TMessage &Msg); // 訊息分發
__published:
__property TMyEvent OnMyEvent = {read=FOnMyEvent, write=FOnMyEvent};
};
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(WM_MYMESSAGE, TMessage, DoSomething)
END_MESSAGE_MAP(TControl)
void __fastcall TMyControl::DoMyEvent(int P1, int P2) {
if (FOnMyEvent) FOnMyEvent(this, P1, P2); // 呼叫使用者寫的事件處理常式
}
void __fastcall TMyControl::WndProc(TMessage &Msg) {
if (Msg.Msg == WM_MYMESSAGE) {
DoMyEvent(Msg.WParam, Msg.LParam); // 解封裝訊息參數
} else {
TWinControl::WndProc(Msg); // 其餘訊息交給基類
}
}
__closure,否則無法綁定具體物件實例。DoMyEvent 允許衍生類覆寫觸發邏輯(如加入前置檢查)。__published + __property 讓 IDE 自動識別並顯示在事件頁籤。「自訂事件是元件化開發的核心:將底層訊息機制隱藏,暴露領域語言層級的互動介面。」