BCB/Delphi 核心 VCL 封裝了 Windows 訊息機制。理解 VCL 如何分派訊息,是掌握進階開發的關鍵。本系列三篇文章從源碼層面剖析。
#define BEGIN_MESSAGE_MAP \
virtual void __fastcall Dispatch(void *Message) { \
switch (((PMessage)Message)->Msg) {
#define VCL_MESSAGE_HANDLER(msg, type, meth) \
case msg: \
meth(*((type *)Message)); \
break;
#define END_MESSAGE_MAP(base) \
default: \
base::Dispatch(Message); \
break; \
} \
}
class TMyForm : public TForm {
protected:
void __fastcall OnPaint(TMessage &Msg);
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(WM_PAINT, TMessage, OnPaint)
END_MESSAGE_MAP(TForm)
};
virtual void __fastcall Dispatch(void *Message) {
switch (((PMessage)Message)->Msg) {
case WM_PAINT:
OnPaint(*((TMessage *)Message));
break;
default:
TForm::Dispatch(Message);
break;
}
}
TObject 為所有 VCL 類別基類,定義虛擬 Dispatch 與 DefaultHandlerDispatch 即可自訂訊息分派邏輯Dispatch 找不到對應處理,最終呼叫 DefaultHandler (預設呼叫 DefWindowProc)MESSAGE_HANDLER 巨集,與 VCL 衝突VCL_MESSAGE_HANDLER 避免衝突MESSAGE_HANDLER 會自動映射為 VCL_MESSAGE_HANDLER
[系統] → [視窗程序 MainWndProc] → [WndProc] → [Dispatch] → [訊息對應巨集 case 分支]
↓ 未匹配
[父類別 Dispatch] → [DefaultHandler]
| 優點 | 缺點 |
|---|---|
| 語法清晰、集中管理訊息處理 | 需在類別宣告中使用巨集,較非標準 C++ |
| 型別安全 (自動轉型為指定 TMessage 衍生類型) | 僅適用於 VCL 類別體系 |
| 自動維護繼承鏈 (END_MESSAGE_MAP 指定父類別) | 巨集展開後難以除錯 (需看預處理輸出) |
方法二:重載 TControl.WndProc,更早攔截訊息,處理滑鼠/鍵盤等預處理邏輯。