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

C++ Builder 訊息處理機制深度解析與自訂訊息實作

     編輯:關於C++

Windows 訊息驅動架構回顧

  • 系統訊息佇列 → 應用程式訊息佇列
  • 訊息迴圈:GetMessage → TranslateMessage → DispatchMessage
  • 每個視窗在核心註冊視窗程序,DispatchMessage 依 HWND 找到並呼叫

VCL 封裝架構

Application 類別

  • 封裝 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: 分派。

自訂訊息實作完整範例

1. 定義訊息結構 (可選,複雜參數時)


#define WM_MY_CUSTOM_MSG (WM_USER + 100)

struct TMyCustomMsg {
    UINT Msg;
    int  Param1;
    int  Param2;
    LRESULT Result;
};

2. 發送端


// 同步發送 (需結果)
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);

3. 接收端 (控制項類別中)


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 vs SendMessage vs PostMessage

特性Perform()SendMessage()PostMessage()
需 HWND否 (需 VCL 實例)是是
同步性同步同步非同步
訊息佇列不經佇列 (直接 Dispatch)不經佇列 (直接呼叫視窗程序)經佇列
適用對象VCL 控制項任何 HWND任何 HWND
跨執行緒否 (需同執行緒)是 (系統處理附著)是

常見陷阱

  • 忘記 END_MESSAGE_MAP(base):導致父類別訊息無法處理
  • 訊息 ID 衝突:自訂訊息建議使用 WM_APP 為基底 (WM_APP + n)
  • 在建構函式中發送訊息:控制項尚未完全建立,可能存取違規
  • 大量訊息處理阻塞 UI:耗時操作應放入執行緒或 PostMessage 分批處理
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved