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

深入 VCL 訊息機制 (二):TControl.WndProc 核心邏輯解析

     編輯:VC 教學

VCL 繼承鏈回顧

TObject → TPersistent → TComponent → TControl
  • TPersistent:提供串流儲存/載入屬性能力(DFM 依賴此機制)。
  • TComponent:所有元件基類,擁有擁有者/被擁有者關係。
  • TControl:所有可視元件基類,定義位置、大小、顯示、滑鼠/鍵盤互動等核心行為。

TControl.WndProc 完整源碼逐段解析

源碼位置:$(BCB)\Source\Vcl\Controls.pas(或 Controls.hpp)。

1. 設計模式訊息處理

if (csDesigning in ComponentState) then begin
    Form := GetParentForm(Self);
    if (Form <> nil) and (Form.Designer <> nil) and
       Form.Designer.IsDesignMsg(Self, Message) then Exit;
end

設計時期將特定訊息(如選取、拖曳)導向表單設計器處理,避免干擾運行邏輯。

2. 鍵盤訊息轉發給表單

else if (Message.Msg >= WM_KEYFIRST) and (Message.Msg <= WM_KEYLAST) then begin
    Form := GetParentForm(Self);
    if (Form <> nil) and Form.WantChildKey(Self, Message) then Exit;
end

讓表單優先處理快捷鍵、對話框導航鍵(Tab/Enter/Esc)等。

3. 滑鼠訊息深度處理(核心)

else if (Message.Msg >= WM_MOUSEFIRST) and (Message.Msg <= WM_MOUSELAST) then begin
    // 3.1 雙擊轉單擊(若未啟用 csDoubleClicks)
    if not (csDoubleClicks in ControlStyle) then
        case Message.Msg of
            WM_LBUTTONDBLCLK, WM_RBUTTONDBLCLK, WM_MBUTTONDBLCLK:
                Dec(Message.Msg, WM_LBUTTONDBLCLK - WM_LBUTTONDOWN);
        end;

    // 3.2 具體滑鼠訊息分派
    case Message.Msg of
        WM_MOUSEMOVE:
            Application.HintMouseMessage(Self, Message); // 提示顯示邏輯
        WM_LBUTTONDOWN, WM_LBUTTONDBLCLK:
            begin
                if FDragMode = dmAutomatic then begin
                    BeginAutoDrag; Exit; // 自動拖放模式
                end;
                Include(FControlState, csLButtonDown); // 記錄左鍵按下狀態
            end;
        WM_LBUTTONUP:
            Exclude(FControlState, csLButtonDown); // 清除狀態
    end;
end

4. VCL 自訂訊息 CM_VISIBLECHANGED

else if Message.Msg = CM_VISIBLECHANGED then
    with Message do
        SendDockNotification(Msg, WParam, LParam);

CM_* 系列為 VCL 內部訊息,不在 Windows SDK 定義中。此處處理停靠/浮動可視狀態變更通知。

5. 最後分派:Dispatch(Message)

將訊息傳遞給 Dispatch 虛擬方法,進入訊息映射表或動態方法查找對應處理器(如 OnClick, OnMouseDown 事件)。

關鍵設計洞察

機制說明
訊息優先級設計模式 > 鍵盤轉發 > 滑鼠處理 > CM_* 內部 > Dispatch
滑鼠狀態機FControlState 位標記追蹤按下/釋放/雙擊,支援拖放邏輯
Hint 整合WM_MOUSEMOVE 直接呼叫 Application.HintMouseMessage
自動拖放dmAutomatic 讓 VCL 自動啟動 BeginDrag

實戰啟示

  • 繼承 TControl 開發自訂元件時,務必呼叫 inherited 保留上述核心邏輯。
  • 若需攔截滑鼠訊息,建議重寫 WndProc 並在 case WM_*: 處理完後 inherited,而非完全取代。
  • CM_* 訊息可用於元件間解耦通訊(如 CM_ENABLEDCHANGED, CM_FONTCHANGED)。

TControl.WndProc 處理流程圖

掌握 TControl.WndProc,即掌握了 VCL 可視元件輸入處理的心臟。

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