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

DBGrid 滑鼠滾輪支援:子類化攔截 WM_MOUSEWHEEL 實作

     編輯:關於C++

問題

TDBGrid 預設不處理滑鼠滾輪訊息,資料量大時僅能靠捲軸翻頁,體驗不佳。

解決方案:子類化攔截 WM_MOUSEWHEEL

透過 SetWindowLong(GWL_WNDPROC) 替換視窗程序,在自訂 WindowProc 中處理滾輪訊息並轉發垂直捲動命令。

完整實作程式碼

// 全域變數保存原始 WindowProc
FARPROC OldProc = NULL;

// 新視窗程序
LRESULT CALLBACK DBGridProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    if (uMsg == WM_MOUSEWHEEL) {
        short zDelta = (short)HIWORD(wParam); // 滾輪增量 (+120/-120)
        if (zDelta > 0)
            ::PostMessage(hWnd, WM_VSCROLL, SB_LINEUP, 0);   // 向上一行
        else
            ::PostMessage(hWnd, WM_VSCROLL, SB_LINEDOWN, 0); // 向下一行
        return 0; // 已處理
    }
    // 其他訊息交給原始程序
    return ::CallWindowProc(OldProc, hWnd, uMsg, wParam, lParam);
}

// 表單啟動時掛鉤
void __fastcall TMainForm::FormShow(TObject* Sender) {
    // ... 資料庫連線程式碼 ...
    OldProc = (FARPROC)::SetWindowLong(DBGrid->Handle, GWL_WNDPROC, (LONG)DBGridProc);
}

// 表單關閉時還原
void __fastcall TMainForm::FormClose(TObject* Sender, TCloseAction& Action) {
    ::SetWindowLong(DBGrid->Handle, GWL_WNDPROC, (LONG)OldProc);
    // ... 關閉資料庫 ...
}

關鍵點解析

  • HIWORD(wParam) 取得滾輪增量(WHEEL_DELTA = 120)
  • 使用 PostMessage 非同步發送 WM_VSCROLL,避免重入問題
  • SB_LINEUP/SB_LINEDOWN 對應單行捲動
  • CallWindowProc 確保原有訊息處理邏輯不受影響
  • 64 位元相容:實際專案請用 SetWindowLongPtr/GetWindowLongPtr 並改用 LONG_PTR

進階擴充

  • 加速捲動:累積 zDelta,超過閾值改發送 SB_PAGEUP/SB_PAGEDOWN
  • Shift+滾輪 = 水平捲動:檢查 LOWORD(wParam) & MK_SHIFT 發送 WM_HSCROLL
  • 通用化:封裝為 TDBGrid 衍生類別,建構子自動掛鉤,解構子自動還原

替代方案比較

方案優點缺點
子類化 (本文)無侵入、通用、效能佳需注意 64 位元指標截斷
Application->OnMessage純 VCL、無 API全域攔截、效能稍差
衍生 TDBGrid 覆寫 WndProc物件導向、封裝性好需替換專案中所有 DBGrid
第三方元件功能豐富增加依賴、體積大
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved