Windows 以消息驅動:用戶操作(鼠標、鍵盤)、系統事件(繪製、定時器)均轉化為消息投遞到窗口隊列。C++Builder VCL 封裝常用消息為事件(OnClick、OnPaint),但部分消息(WM_NC* 非客戶區、WM_COPYDATA、自定義消息、Winsock 異步通知)無對應事件,需直接處理。
struct TMessage {
Cardinal Msg; // 消息 ID
union {
struct {
Word WParamLo, WParamHi;
Word LParamLo, LParamHi;
Word ResultLo, ResultHi;
};
struct {
Longint WParam, LParam, Result;
};
};
};
struct TWMNCHitTest {
Cardinal Msg;
Longint Unused;
union {
struct {
TSmallPoint Pos; // XPos, YPos
Longint Result;
};
struct {
Short XPos, YPos;
};
};
};
兩結構大小相同,可通過 reinterpret_cast 或 C 風格強轉互換,類似 union 用法。
void __fastcall WmNcHitTest(TWMNCHitTest& Message);。BEGIN_MESSAGE_MAP ... MESSAGE_HANDLER(WM_NCHITTEST, TWMNCHitTest, WmNcHitTest) ... END_MESSAGE_MAP。Message 字段,設置 Message.Result 返回值,或調用 DefaultHandler(Message) 轉交默認處理。#define WM_MY_CUSTOM (WM_USER + 100)
// 發送
PostMessage(Handle, WM_MY_CUSTOM, wParam, lParam);
// 接收類中
MESSAGE_HANDLER(WM_MY_CUSTOM, TMessage, OnMyCustom);
void __fastcall TForm1::WmNcHitTest(TWMNCHitTest& Msg) {
// 讓標題栏區域也能拖動窗口
if (Msg.Result == HTCLIENT) Msg.Result = HTCAPTION;
}
void __fastcall TForm1::WmCopyData(TWMCopyData& Msg) {
PCOPYDATASTRUCT pcds = Msg.CopyDataStruct;
if (pcds->dwData == MY_DATA_ID) {
string data((char*)pcds->lpData, pcds->cbData);
// 處理數據
}
Msg.Result = 1; // 表示已處理
}
DefaultHandler 保證默認行為(如繪製、焦點管理)不丟失。TWM*)提高代碼可讀性與類型安全。WParam/LParam/Result 為 LONG_PTR,避免截斷。