2017-07-06 58 views
1

我有(舊...)代碼在SetScrollRange()的背景中更新滾動條位置和最小最大值,但此代碼不應該在用戶是拖動滾動條旋鈕,因爲它使旋鈕在視覺上跳回到原始位置,然後在拖動或釋放鼠標時跳回到用戶選擇的位置。如何檢測用戶正在拖動滾動條旋鈕

是否有一些簡單的方法來檢測拖動正在進行?

+0

['SB_THUMBTRACK'](https://msdn.microsoft.com/en-us/library/windows/desktop/bb787577(v = vs.85).aspx) – zett42

+0

@ zett42那會告訴我它被拖動最近在處理該消息時,而不是在處理其他消息時(在本例中爲後臺計時器)。 –

回答

1

我可以想到兩種方法來做到這一點。簡單(和哈希)的方法是調用GetCapture()。它將返回已捕獲鼠標的當前窗口的HWND值,如果未捕獲到鼠標,則返回NULL。這只是表示用戶在滾動條控件內按下了鼠標按鈕而不釋放鼠標按鈕。

更好的方法是將控件進行子類化。下面是關於如何你可以設置一個標誌一些示例代碼,如果滾動條的「拇指」被拖動:

// Somewhere in your code, subclass the scrollbar 
WNDPROC originalScrollBarWndProc = (WNDPROC) SetWindowLongPtr(scrollBarHwnd, GWLP_WNDPROC, (LONG_PTR) myScrollBarWndProc); 

LRESULT CALLBACK myScrollBarWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) 
{ 
    switch(message) 
    { 
     case WM_LBUTTONDOWN: 
     { 
      // Get Y position of the mouse 
      uint16_t mouseYPos = HIWORD(lParam); // Change this to LOWORD for horizontal scrollbars 

      // Get the top and bottom coordinates of the scrollbar thumb 
      SCROLLBARINFO sbi = {0}; 
      sbi.cbSize = sizeof(SCROLLBARINFO); 

      if(GetScrollBarInfo(hwnd, OBJID_CLIENT, &sbi) == 0) 
      { 
       // Failed to get scroll bar info, handle however you want 
       break; 
      } 

      // Check if the WM_LBUTTONDOWN event happened over the scrollbar thumb 
      if(mouseYPos >= sbi.xyThumbTop && mouseYPos <= sbi.xyThumbBottom) 
      { 
       // Set a flag to indicate that the thumb is being "dragged" 
       // I chose to do this using SetWindowLongPtr; Do it however you like. 
       SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) 1); 
      } 
     } 
     break; 

     case WM_LBUTTONUP: 
     { 
      // Mouse button was released, clear the flag 
      SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR) 0); 
     } 
     break; 

     /* ... other cases here, if needed ... */ 
    } 

    return CallWindowProc(originalScrollBarWndProc, hwnd, message, wParam, lParam); 
} 

使用上面的代碼,所有你需要做的就是調用GetWindowLongPtr(scrollBarHwnd,GWLP_USERDATA),並檢查如果該值爲0或1以查看是否被拖動。

我不是積極的,這是最好的方法的問題,但我相信它至少是一個很好的工作。

2

當用戶圍繞滾動條的拇指拖動,滾動條的所有者窗口接收WM_VSCROLL(垂直)或WM_HSCROLL(水平)消息(取決於滾動條的定向),其中wParam值的LO-字被設定到SB_THUMBTRACK並且hi-word被設置爲新的位置。

當用戶釋放拇指,所有者窗口接收到兩個最終WM_(V|H)SCROLL消息:

  • 第一消息具有wParam值設置爲SB_THUMBPOSITION和Hi-字設置爲新的LO-字位置。
  • 第二條消息的012字段爲wParam,設置爲TB_ENDTRACK

您可以繼承擁有滾動條的UI控件來攔截這些消息。當看到任何WM_(V|H)SCROLL消息時,請勿更新滾動條,直至看到SB_ENDTRACK通知。

+0

因此,當我看到'TB_ENDTRACK'時,我可以在獲得第一個'SB_THUMBTRACK'時設置一些全局/靜態狀態並重置該狀態? –

+1

@ErikElmgren是的 –