Windows 是訊息驅動的搶占式多任務系統。核心流程:
GetMessage → TranslateMessage → DispatchMessage。while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg); // 虛擬鍵 → 字元訊息 WM_CHAR
DispatchMessage(&msg); // 送達視窗程序
}
Application->Run() 啟動內建迴圈,等同上述標準迴圈,並整合 OnIdle、OnMessage 等擴展點。
TWinControl 衍生類別對應一個 WNDCLASS(或共用 VCL.Window)。StdWndProc(組裝語言 Thunk)。StdWndProc → TWinControl.MainWndProc → WndProc// 簡化流程
StdWndProc(hWnd, Msg, wParam, lParam)
→ 取得 TWinControl 實例 (via GetWindowLongPtr GWLP_USERDATA)
→ MainWndProc(Message)
→ 嘗試例外保護
→ WndProc(Message) // 虛擬方法,可重寫
→ 若無處理 → DefaultHandler(Message)
→ DefWindowProc // 系統預設處理
OnClick, OnMouseDown, OnKeyPress 等。Dispatch 透過訊息映射表分派。BEGIN_MESSAGE_MAP)BEGIN_MESSAGE_MAP
VCL_MESSAGE_HANDLER(WM_LBUTTONDOWN, TMessage, WMLButtonDown)
VCL_MESSAGE_HANDLER(WM_COPYDATA, TWMCopyData, WMCopyData)
END_MESSAGE_MAP(TForm)
switch(Message.Msg) 分派。END_MESSAGE_MAP(ParentClass) 未命中時呼叫父類 Dispatch。WndProc / MainWndProcWM_MOUSEMOVE, WM_PAINT)、訊息過濾、前置處理。inherited 維持 VCL 內部邏輯。// 1. 定義訊息 ID (WM_USER 以上)
#define WM_MY_CUSTOM (WM_USER + 100)
// 2. 定義訊息結構 (可選,便於參數傳遞)
struct TMyCustomMsg : public TMessage {
int Data1;
int Data2;
};
// 3. 發送訊息
PostMessage(TargetWnd, WM_MY_CUSTOM, Data1, Data2);
// 或跨進程
SendMessageTimeout(hWnd, WM_MY_CUSTOM, wParam, lParam,
SMTO_NORMAL, 1000, &result);
// 4. 接收端:訊息映射表
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_MY_CUSTOM, TMyCustomMsg, OnMyCustom)
END_MESSAGE_MAP(TForm)
void __fastcall TForm1::OnMyCustom(TMyCustomMsg &Msg)
{
// Msg.Data1, Msg.Data2 直接可用
ShowMessage(Format("收到: %d, %d", [Msg.Data1, Msg.Data2]));
}
| 機制 | 查找效能 | 適用場景 | 維護性 |
|---|---|---|---|
| 事件 (OnXxx) | O(1) 映射表 | 標準 UI 互動 | ★★★★★ |
| 訊息映射表 | O(n) switch | 非標準訊息、自訂訊息 | ★★★★☆ |
| 重寫 WndProc | O(1) 直接 | 高頻訊息、前置過濾 | ★★★☆☆ |
inherited:導致 Hint、DragDrop、Focus 等核心功能失效。WM_USER + offset(視窗私有)或 RegisterWindowMessage(全域唯一)。PostMessage。
理解這套從 OS 到 VCL 的訊息傳遞鏈路,是解決疑難雜症、實現高階互動的關鍵鑰匙。