VCL 封裝了常用訊息(Click、Paint、KeyDown 等),但大量 Windows 訊息(WM_NCHITTEST, WM_DEVICECHANGE, WM_POWERBROADCAST 等)未暴露為事件。訊息映射表(BEGIN_MESSAGE_MAP)是填補這些缺口的標準機制。
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(, , )
...
END_MESSAGE_MAP()
Message:Windows 訊息常數(WM_NCHITTEST 等)。MessageStruct:參數結構,基本型為 TMessage(含 Msg, WParam, LParam, Result)。Handler:處理函數名,簽名 void __fastcall Handler(TMessage &Msg)。BaseClass:父類別名,未命中時呼叫 BaseClass::Dispatch。需求:移除標題列,但保留拖動移動視窗功能。
CreateParams)// 標頭檔
protected:
virtual void __fastcall CreateParams(TCreateParams &Params);
// 實作檔
void __fastcall TForm1::CreateParams(TCreateParams &Params)
{
TForm::CreateParams(Params);
Params.Style &= ~WS_CAPTION; // 關鍵:移除 WS_CAPTION 風格
}
WM_NCHITTEST// 標頭檔 private 區
void __fastcall WMNCHitTest(TMessage &Message);
// protected 區
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_NCHITTEST, TMessage, WMNCHitTest)
END_MESSAGE_MAP(TForm)
void __fastcall TForm1::WMNCHitTest(TMessage &Message)
{
// 僅在左鍵按下時偽裝為標題列
if (GetAsyncKeyState(VK_LBUTTON) < 0) {
Message.Result = HTCAPTION; // 告訴系統:滑鼠在標題列上
} else {
Message.Result = HTCLIENT; // 否則:在客戶區
}
}
| API | 用途 | 關鍵參數 |
|---|---|---|
GetAsyncKeyState | 即時檢查虛擬鍵狀態(非訊息佇列) | 回傳負值 = 高位置 1 = 鍵按下 |
WM_NCHITTEST | 非客戶區命中測試,優先於所有滑鼠訊息 | 回傳值決定後續訊息(HTCAPTION→WM_NCLBUTTONDOWN→移動) |
HTCAPTION | 標題列命中代碼 | 系統據此啟動視窗移動邏輯 |
DefWindowProc | 預設處理:根據滑鼠座標回傳 HTCLIENT/HTBORDER/HTCAPTION 等 | 我們透過攔截覆寫此行為 |
void __fastcall TForm1::WMNCHitTest(TMessage &Message)
{
TPoint pt = { LOWORD(Message.LParam), HIWORD(Message.LParam) };
pt = ScreenToClient(pt);
// 1. 右下角縮放區 (16x16)
if (pt.x >= ClientWidth - 16 && pt.y >= ClientHeight - 16) {
Message.Result = HTBOTTOMRIGHT; return;
}
// 2. 底邊/右邊縮放
if (pt.y >= ClientHeight - 4) { Message.Result = HTBOTTOM; return; }
if (pt.x >= ClientWidth - 4) { Message.Result = HTRIGHT; return; }
// 3. 標題列區域 (頂部 30px)
if (pt.y < 30) {
if (GetAsyncKeyState(VK_LBUTTON) < 0)
Message.Result = HTCAPTION;
else
Message.Result = HTCLIENT;
return;
}
// 4. 其他客戶區
Message.Result = HTCLIENT;
}
| 訊息 | 典型用途 | 建議結構 |
|---|---|---|
| WM_NCHITTEST | 無標題拖動、自訂縮放邊緣 | TMessage |
| WM_DEVICECHANGE | USB 插拔、磁碟插入偵測 | TWMDeviceChange |
| WM_POWERBROADCAST | 待機/喚醒/電源狀態變更 | TWMPowerBroadcast |
| WM_DWMCOMPOSITIONCHANGED | DWM 啟用/停用 (Vista+) | TMessage |
| WM_TOUCH | 觸控輸入原始資料 | TWMTouch |
| WM_GESTURE | 手勢識別 (縮放/旋轉) | TWMGesture |
OutputDebugString 印出 Message.Msg 確認訊息到達。Handler 設置斷點,檢查 WParam/LParam/Result。
訊息映射表是 VCL 開發者通往 Windows 核心訊息層的標準通道,掌握它即掌握了視窗行為的終極控制權。