MFC:拖动滚动条拇指时的奇怪行为

MFC: strange behavior when dragging scrollbar thumb

我使用滚动条显示大量多行数据(一些背景请参考我之前的问题:MFC: how to reduce the time cost of OnInitialUpdate() for scrolling?)。

滚动功能在以下情况下工作正常:(1) 单击箭头按钮,(2) 单击滚动轴或 (3) 滚动鼠标滚轮;内容正确向上或向下移动。但是当我拖动滚动拇指时,除非距离非常小,否则它的行为并不像预期的那样。

再拖一点点,例如向前,它可能会向后跳,有时会一直跳到开头。当鼠标松开时它永远不会停留,我也从来没有成功地将拇指一直拖到最后一条记录。

仔细一看,"GetClipBox(...)" 似乎不是 return 正确的数据。例如,如果我一直拖到最后,此函数将 return rect.top 等于零。由于我依靠 return 值来计算要绘制的记录集,所以其余的都搞砸了。

可在此处访问最小的可重现示例:https://138.197.210.223/test/My.tar.gz。测试时,将拇指一直拖到最后效果更佳。

您是否添加了WM_HSCROLL orWM_VSCROLL消息?

The WM_HSCROLL message is sent to a window when a scroll event occurs in the window's standard horizontal scroll bar. This message is also sent to the owner of a horizontal scroll bar control when a scroll event occurs in the control.

The WM_VSCROLL message is sent to a window when a scroll event occurs in the window's standard vertical scroll bar. This message is also sent to the owner of a vertical scroll bar control when a scroll event occurs in the control.

建议您尝试在OnHScroll函数或OnVScroll函数中加入如下代码:

case SB_THUMBPOSITION:
    pScrollBar->SetScrollPos(nPos);
    break;

这是由于 16-bit limit of the WM_VSCROLL message。实际上,限制是 32767,而不是文档中所说的 65535。很久以前在一个项目中遇到了同样的问题。

解决方法是修改 WM_VSCROLL 消息处理,使其使用 GetScrollInfo() 函数返回的 32 位值。覆盖 OnVScroll()(转到 Class 查看,select 您的视图并添加 WM_VSCROLL 消息处理程序):

void CMyView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
    // Workaround the 16-bit limitation
    if (nSBCode == SB_THUMBPOSITION || nSBCode == SB_THUMBTRACK)
    {
        SCROLLINFO si;
        si.cbSize = sizeof(si);
        si.fMask = SIF_ALL;
        ::GetScrollInfo(m_hWnd, SB_VERT, &si);
        // Set nPos to the 32-bit value
        nPos = si.nTrackPos;
    }
    CScrollView::OnVScroll(nSBCode, nPos, pScrollBar);
}

这应该可以解决问题。