GetMessage → TranslateMessage → DispatchMessageDispatchMessage 依 HWND 找到並呼叫WinMain、初始化、訊息迴圈、例外處理Application->Run() 內含訊息迴圈,直到 Terminated 為真
// 簡化流程
MainWndProc (非虛擬) → WndProc (虛擬) → Dispatch (虛擬, 繼承自 TObject)
| 方法 | 角色 | 可覆寫 |
|---|---|---|
| MainWndProc | 系統呼叫入口,例外處理後呼叫 WndProc | 否 (非虛擬) |
| WndProc | 核心分派,依訊息類型預處理 (拖放、鍵盤、滑鼠...) | 是 (虛擬) |
| Dispatch | 依 TMessage.Msg 查找對應處理方法,沿繼承鏈向上尋找 | 是 (虛擬) |
| DefaultHandler | 最終預設處理 (呼叫 DefWindowProc) | 是 (虛擬) |
定義於 sysmac.h:
#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 TMyControl : public TCustomControl {
protected:
void __fastcall OnMyMessage(TMessage &Msg);
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(WM_USER + 100, TMessage, OnMyMessage)
END_MESSAGE_MAP(TCustomControl)
};
展開後等同於在 Dispatch 中增加 case WM_USER+100: 分派。
#define WM_MY_CUSTOM_MSG (WM_USER + 100)
struct TMyCustomMsg {
UINT Msg;
int Param1;
int Param2;
LRESULT Result;
};
// 同步發送 (需結果)
TMyCustomMsg msg;
msg.Msg = WM_MY_CUSTOM_MSG;
msg.Param1 = 123;
msg.Param2 = 456;
LRESULT res = TargetControl->Perform(WM_MY_CUSTOM_MSG, msg.Param1, msg.Param2);
// 或跨視窗 (需 HWND)
SendMessage(hTargetWnd, WM_MY_CUSTOM_MSG, 123, 456);
// 非同步張貼
PostMessage(hTargetWnd, WM_MY_CUSTOM_MSG, 123, 456);
class TMyControl : public TCustomControl {
protected:
void __fastcall HandleCustomMsg(TMessage &Msg) {
int p1 = Msg.WParam;
int p2 = Msg.LParam;
// 處理邏輯...
Msg.Result = 1; // 回傳值
}
BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(WM_MY_CUSTOM_MSG, TMessage, HandleCustomMsg)
END_MESSAGE_MAP(TCustomControl)
};
| 特性 | Perform() | SendMessage() | PostMessage() |
|---|---|---|---|
| 需 HWND | 否 (需 VCL 實例) | 是 | 是 |
| 同步性 | 同步 | 同步 | 非同步 |
| 訊息佇列 | 不經佇列 (直接 Dispatch) | 不經佇列 (直接呼叫視窗程序) | 經佇列 |
| 適用對象 | VCL 控制項 | 任何 HWND | 任何 HWND |
| 跨執行緒 | 否 (需同執行緒) | 是 (系統處理附著) | 是 |
WM_APP 為基底 (WM_APP + n)PostMessage 分批處理