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

C++Builder TMouse 類詳解:滑鼠狀態感知、拖曳閾值控制、滾輪訊息與多顯示器座標實戰

     編輯:關於C++

C++Builder TMouse 類詳解:滑鼠狀態感知、拖曳閾值控制、滾輪訊息與多顯示器座標實戰

TMouse 封裝系統滑鼠狀態,全域單例 Mouse(定義於 Controls.hpp)提供游標位置、捕獲視窗、拖曳行為參數、滾輪訊息常數、硬體存在性檢測等輕量級介面。本文系統講解核心屬性、拖曳閾值機制、滾輪訊息處理、多顯示器座標轉換與常見陷阱。

類層次與單例

TObject
  └── TMouse  // 非元件,全域單例 Mouse

核心屬性

屬性類型說明
CursorPosTPoint螢幕絕對座標(虛擬桌面座標系)
CaptureHWND當前捕獲滑鼠訊息的視窗句柄(0 表示無)
DragImmediateBooleantrue:按下即啟動拖曳;false:需移動 DragThreshold 像素
DragThresholdInteger啟動拖曳所需移動像素(預設 5),DragImmediate=false 時生效
MousePresentBoolean系統是否有滑鼠裝置
WheelPresentBoolean滑鼠是否有滾輪
WheelScrollLinesInteger每滾輪刻度捲動行數(控制面板設定,通常 3)
RegWheelMessageUINT系統滾輪訊息常數(RegisterWindowMessage("MSWHEEL_ROLLMSG"))

構造與初始化

constructor Create;  // 內部調用
// 初始值
DragImmediate = true;
DragThreshold = 5;
WheelScrollLines = 系統設定值;
RegWheelMessage = RegisterWindowMessage(MSH_MOUSEWHEEL);

拖曳閾值機制深度解析

VCL 拖曳啟動邏輯(TControl::MouseDown → BeginDrag):

if (Mouse->DragImmediate) {
    BeginDrag(true);  // 立即進入拖曳模式
} else {
    // 進入「潛在拖曳」狀態,等待 MouseMove 累積位移
    // 當 |DeltaX| + |DeltaY| >= DragThreshold 時自動 BeginDrag(true)
}
  • DragImmediate=true:適合精確定位場景(棋盤、流程圖節點),但易誤觸發。
  • DragImmediate=false + DragThreshold=3~5:平衡誤觸與響應,推薦預設值 5。
  • 運行時調整:可針對特定控件在 OnMouseDown 臨時修改 Mouse->DragThreshold,離開時恢復。

滾輪訊息處理

// 訊息常數(全域唯一)
const UINT WM_MOUSEWHEEL = 0x020A;  // 標準垂直滾輪
const UINT WM_MOUSEHWHEEL = 0x020E; // 水平滾輪 (Win Vista+)

// 在控件訊息處理器中
MESSAGE void __fastcall WMMouseWheel(TMessage& Msg) {
    if (Msg.Msg == Mouse->RegWheelMessage) {  // 兼容舊版註冊訊息
        int zDelta = (short)HIWORD(Msg.WParam);  // ±120 為一檔
        int lines = zDelta * Mouse->WheelScrollLines / 120;
        // 處理捲動...
    }
}

// 高精度滾輪 (Win10 1809+)
// 使用 WM_MOUSEWHEEL + GET_WHEEL_DELTA_WPARAM 宏
// 支援高解析度滾輪(zDelta 非 120 倍數)

多顯示器座標轉換

// 螢幕絕對座標 → 客戶區座標
TPoint clientPt = Control->ScreenToClient(Mouse->CursorPos);

// 多監視器虛擬桌面座標系說明
// 主監視器左上角為 (0,0)
// 次監視器在左側 → 負 X 座標
// 次監視器在上方 → 負 Y 座標
// 使用 GetMonitorInfo / MonitorFromPoint 判斷所在監視器

捕獲機制

  • Control->Capture = true → SetCapture(Handle) → Mouse->Capture = Handle。
  • 捕獲期間所有滑鼠訊息導向該視窗,即使游標移出客戶區。
  • ReleaseCapture() → Mouse->Capture = 0。
  • 模態對話框/彈出選單自動捕獲,關閉自動釋放。

常見陷阱

現象原因對策
拖曳不啟動DragMode=dmManual 但未呼叫 BeginDrag在 OnMouseDown 呼叫 BeginDrag(false) 或設 DragMode=dmAutomatic
滾輪不觸發控件未處理 RegWheelMessage 或 WM_MOUSEWHEEL重寫 WndProc 或使用 OnMouseWheel 事件 (VCL 內部已分發)
CursorPos 為負值游標在主監視器左/上側的次監視器正常現象,轉換客戶區座標用 ScreenToClient
WheelScrollLines 讀取為 0系統設定「一次捲動一頁」視為「大量捲動」,自行定義行數如 20
MousePresent=false 但有觸控板API 僅檢測傳統滑鼠觸控板通常模擬滑鼠,實際可用

現代化擴展建議

  1. 高精度滾輪:Win10 1809+ 支援 WM_MOUSEWHEEL 非 120 倍數 zDelta,建議累積餘量平滑捲動。
  2. 觸控/手勢:TMouse 無觸控支援,需用 WM_TOUCH / WM_GESTURE 或 TTouchManager (VCL 10.3+)。
  3. 游標隱藏/自定義:ShowCursor(false) + SetCursor(LoadCursor(...)),或 Screen->Cursors 註冊動畫光標。

TMouse 雖輕量,卻是滑鼠交互行為的「中央配置中心」。理解 DragImmediate/Threshold 的雙模式、RegWheelMessage 的版本演進、虛擬桌面座標系,即能精準控制從傳統滑鼠到高精度滾輪、多監視器環境下的交互體驗。

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