We help IT Professionals succeed at work.

Replacing scrollbars in list control

paulburns asked
I have a touch screen application for which the normal scroll bars for navigating a list control are useless, so I need to replace them with something easier to use. I thought of using buttons...

- button for moving up one page
- button for moving up one list entry
- button for moving down one list entry
- button for moving down one page

Questions are:

1. How would I implement the buttons to do those fuunctions?
2. How do I disable the normal scroll bars from appearing in the list control?
Watch Question

Author of the Year 2009
You can use CListCtrl::Scroll( CSize(0,yDeltaInPixels) ) to scroll the list.

You can add the LVS_NOSCROLL style, but that gets rid of
the headers.  You can add back the headers (see Q137520 or I can show the MFC code), but when LVS_NOSCROLL is in effect, the CListCtrl::Scroll() fn (and the LVM_SCROLL message) have no effect.  A possible workaround would be to use CListCtrl::EnsureVisible(...) to move up and down.

Anyway, after thinking about it a while, I have concluded that the scrollbars probably don't really hurt and they *do* provide visual feedback as to how much of the list is visible and how far down the list you have currently scrolled.

Regarding how to handle scrolling with a touch screen:
I think that something along the lines of how the wheelmouse wheel-drag works would be cool.  I'd consider making a four-arrowed control that keep constant track of the finger location (until the finger lifts).  As the finger moves around int this area, the list scrolls to match.  As the finger drags farther from the center, the scrolling speeds up.

Anyway, here is how to get the headers back after you turn on the LVS_NOSCROLL style:

CRect rc;
m_clcList.GetClientRect( &rc );

HD_LAYOUT   hdLayout;

HWND hwndHeader = ::GetWindow(m_clcList.m_hWnd, GW_CHILD);
hdLayout.prc = &rc;
hdLayout.pwpos = &wpos;
Header_Layout( hwndHeader, &hdLayout);
::SetWindowPos( hwndHeader, wpos.hwndInsertAfter,
                     wpos.x, wpos.y, wpos.cx, wpos.cy,
                     wpos.flags | SWP_SHOWWINDOW);

m_clcList.EnsureVisible(0, FALSE ); // top item visible

-- Dan

It seems to me that EnsureVisible also does not have any effect after the LVS_NOSCROLL-flag has been set. This is bad news for me who wants to display a scrollbar of my own in a CListCtrl.

At this point I really don't have a clue on how to accomplish this. Seems I'm going to have to create my own list control... :-(
Author of the Year 2009

Best becareful with your login.  It is a violation of EE rules to have more than one.

Creating your own list view control is unlikely to be your best option.  If the EnsureVisible is the only remaining difficulty, just write your own version of it.

-- Dan


thats not me, I dont know who that is.

I went with your suggestion of leaving the scrollbars in, though it takes up precious screen real-estate.

sorry for leaving this so long , i had forgot about it. I am in the process of cleaning up my open Q's


I know this is an outdated post now, but here's a workaround (okay, let's just call it a hack):

1. put your CListCtrl in another dialog (container) that you will use as the 'real' control.

2. set the CListCtrl to have no borders, etc... Manage the 3d effect (if desired) in the container.

3. in the InitDialog() portion of your 'container', set the position and size of the list control so that it extends below and to the right of the container by the width of the scrollbars (you can use GetSystemMetrics() to get the size of the scrollbar).

4. You can then use other controls (sliders, buttons, whatever) to generate the appropriate CListCtrl::Scroll() calls.

Sorry, I don't have a sanitized example to include.