如何检测用户正在拖动滚动条旋钮

问题描述 投票:1回答:2

我有(旧的)代码用SetScrollRange()更新背景中的滚动条位置和最小值 - 最大值但是当用户拖动滚动条旋钮时,此代码不应该运行,因为它使旋钮在视觉上跳回到原始位置然后当他拖动或释放鼠标时跳回用户选择的位置。

有没有一些简单的方法来检测拖动是否正在进行?

winapi scrollbar
2个回答
1
投票

我可以想到两种方法来做到这一点。简单(和hacky)的方法是调用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以查看它是否被拖动。

我不是肯定的,这是解决问题的最佳方法,但我确信这至少是一个很好的方法。


4
投票

当用户拖动滚动条的拇指时,滚动条的所有者窗口会收到WM_VSCROLL(垂直)或WM_HSCROLL(水平)消息(取决于滚动条的方向),其中wParam值的lo-word设置为SB_THUMBTRACK和hi-word设置为新位置。

当用户释放拇指时,所有者窗口会收到两条最终的WM_(V|H)SCROLL消息:

  • 第一条消息将wParam值的lo-word设置为SB_THUMBPOSITION,将hi-word设置为新位置。
  • 第二条消息将wParam的单词设为TB_ENDTRACK

您可以子类化拥有滚动条的UI控件来拦截这些消息。当您看到任何WM_(V|H)SCROLL消息时,在看到TB_ENDTRACK通知之前,请不要更新滚动条。

© www.soinside.com 2019 - 2024. All rights reserved.