Wednesday, March 05, 2008

Scrolling Windows

At GIPS, we have our own CWnd derived scroll bar. It is just a "regular old" window with the customary parts of a scroll bar. Up, Down buttons, track and thumb. You attach a window to a scroll bar (not vice versa as you would expect) and it forwards scrolling events to the attached window.


The problem is that scrolling performance is terrible when dragging the thumb
quickly. When you do so each WM_MOUSEMOVE message might span many (10's) pixels
equating to several (2 or more) scroll bar position changes. Root cause of poor
scrolling performance is we process each position change individually. For example if scrolling up we do the following.


for ( UINT i = lastScrollPos; i > newPosition; i-- )
{
attachedWindow->SendMessage(
message,
MAKEWPARAM(SB_LINEUP,0),
NULL );
}


In my case the loop above was running 2-14 times. The solution was to change SB_LINEDOWN to SB_THUMBTRACK and remove the loop.


m_slaveWindow->SendMessage(
message,
MAKEWPARAM( SB_THUMBTRACK, newPosition ),
NULL );


I was still left with an additional problem. List-View doesn't seem to like to get SB_THUMBTRACK directly as noted on CodeGuru:



List control will call GetScrolInfo function to get the current scroll box tracking position, so it is necessary to set the tracking position before sending WM_HSCROLL/WM_VSCROLL(TH_THUMBTRACK) message to it.
Unfortunately, SetScrollInfo function does not work when using

Note that ListCtrl really likes to get scroll notification via LVM_SCROLL. However, the general purpose scroll bar doesn't want to track that level of details. SPY++ revealed that List-View sends a WM_SYSCOMMAND / SC_VSCROLL followed by WM_VSCROLL / TH_THUMBTACK. I tried to send WM_SYSCOMMAND / SC_VSCROLL to no avail.


To resolve the List-View issue I changed the scroll bar to take a boolean indicating if we should use line by line scrolling. So windows, that require line by line scrolling can get the original unoptimized version. By default others get the optimized version.


Related Links:
CListCtrl Scroll Messages
How to skin CListCtrl incuding scrollbars and column headers

No comments: