4
votes

I use scrollbar to show a large piece of data with many lines (for some background please refer to my previous question: MFC: how to reduce the time cost of OnInitialUpdate() for scrolling?).

The scrolling function works fine when: (1) clicking on arrow button, (2) clicking on scroll shaft or (3) rolling the mouse wheel; the content moves upwards or downwards correctly. But when I drag the scroll thumb, it doesn't really behave as expected unless very tiny distance.

When dragging a little bit more, e.g. forward, it could jump back and sometimes all the way to the beginning. It never stays when mouse released, and I never successfully drag the thumb all the way to the last record.

As I take closer look, "GetClipBox(...)" seems not return correct data. For example, if I drag all the way to the end, this function would return rect.top equals to zero. Since I rely on the return value to calculate the set of records to draw, the rest is messed up.

A minimal reproducible example can be accessed here: https://138.197.210.223/test/My.tar.gz. When testing, drag thumb all the way to the end for better effect.

2
Please show a minimal reproducible example. This sounds like everything works as expected, but your calculations are wrong. It's very easy to introduce off-by-one errors in calculating the scroll range.IInspectable
@IInspectable, Please access mre here 138.197.210.223/test/My.tar.gz. When you test, drag the thumb all the way to the end for better effect. Also, I have to use VS-2008. Thank you for the help.user180574

2 Answers

3
votes

This is due to the 16-bit limit of the WM_VSCROLL message. Actually the limit is 32767, not 65535 as the documentation says. Had the same problem in a project a loooong time ago.

The workaround is to modify the WM_VSCROLL message processing so that it uses the 32-bit value returned by the GetScrollInfo() function instead. Override OnVScroll() (go to Class View, select your view and add the WM_VSCROLL message handler):

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);
}

This should fix the problem.

0
votes

Whether you have added WM_HSCROLL orWM_VSCROLL message?

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.

I suggest you could try to add the following code to the OnHScroll function or OnVScroll function:

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