首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

C++Builder 訊息處理機制全景:從 Windows 訊息泵到 VCL 封裝與擴展

     編輯:VC 教學

Windows 訊息驅動架構基石

Windows 是訊息驅動的搶占式多任務系統。核心流程:

  1. 系統訊息佇列:收集硬體輸入、系統事件。
  2. 執行緒訊息佇列:每個 GUI 執行緒擁有獨立佇列。
  3. 訊息迴圈:GetMessage → TranslateMessage → DispatchMessage。
while (GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg); // 虛擬鍵 → 字元訊息 WM_CHAR
    DispatchMessage(&msg);  // 送達視窗程序
}

VCL 如何封裝訊息機制

1. TApplication 內建訊息泵

Application->Run() 啟動內建迴圈,等同上述標準迴圈,並整合 OnIdle、OnMessage 等擴展點。

2. 視窗類別註冊與視窗程序

  • 每個 TWinControl 衍生類別對應一個 WNDCLASS(或共用 VCL.Window)。
  • 視窗程序指向 VCL 統一入口 StdWndProc(組裝語言 Thunk)。

3. StdWndProc → TWinControl.MainWndProc → WndProc

// 簡化流程
StdWndProc(hWnd, Msg, wParam, lParam)
    → 取得 TWinControl 實例 (via GetWindowLongPtr GWLP_USERDATA)
    → MainWndProc(Message)
        → 嘗試例外保護
        → WndProc(Message) // 虛擬方法,可重寫
        → 若無處理 → DefaultHandler(Message)
            → DefWindowProc // 系統預設處理

VCL 訊息處理三大擴展機制

A. 動態方法(事件層)

  • OnClick, OnMouseDown, OnKeyPress 等。
  • 由 Dispatch 透過訊息映射表分派。
  • 優點:設計器支援、直觀、類型安全。

B. 訊息映射表(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) 分派。
  • 適用於無對應事件的 Windows 訊息、自訂訊息。
  • 支援繼承鏈:END_MESSAGE_MAP(ParentClass) 未命中時呼叫父類 Dispatch。

C. 重寫虛擬方法 WndProc / MainWndProc

  • 最底層、最靈活、效能最高(無 switch 查找)。
  • 適用於高頻訊息(WM_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非標準訊息、自訂訊息★★★★☆
重寫 WndProcO(1) 直接高頻訊息、前置過濾★★★☆☆

常見陷阱

  • 忘記 inherited:導致 Hint、DragDrop、Focus 等核心功能失效。
  • 在訊息處理器中執行阻塞操作:凍結 UI 執行緒,改用執行緒或非同步模式。
  • 自訂訊息 ID 衝突:嚴格使用 WM_USER + offset(視窗私有)或 RegisterWindowMessage(全域唯一)。
  • 跨執行緒 SendMessage:會阻塞發送執行緒直到接收端處理完,慎用;優先 PostMessage。

VCL 訊息處理架構圖

理解這套從 OS 到 VCL 的訊息傳遞鏈路,是解決疑難雜症、實現高階互動的關鍵鑰匙。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved