Solved

Why SB_THUMBTRACK does not work in a list control?

Posted on 1998-02-25
8
1,682 Views
Last Modified: 2013-11-20
Hi:

I need to have an external scrollbar control for some other controls, in part for list box and list control ("external" means that I create a scrollbar and redirect its WM_*SCROLL messages to other controls). I have made a test: placed a list box, a list control and a vertical  scrollbar in a dialog, added 100 items to the both lists and set up the scrollbar info. Then in CMyDialog::OnVScroll I write:

void CMyDialog::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
      // TODO: Add your message handler code here and/or call default
      
      if( pScrollBar == 0 ) {
            CDialog::OnVScroll(nSBCode, nPos, pScrollBar);
            return;
      }

      listBox.SendMessage( WM_VSCROLL, MAKEWPARAM( nSBCode, nPos ),
                                    (LPARAM)0 );
      listCtrl.SendMessage( WM_VSCROLL, MAKEWPARAM( nSBCode, nPos ),
                                    (LPARAM)0 );
}

Everything works fine on both controls when I click on the scrollbar's arrows (line up/down) and below/over the thumb (page up/down), but when  I drag the thumb SB_THUMBTRACK/SBTHUMBPOSITION) only the list box is scrolled, the list control has no reaction. But when I drag its own scrollbar it works fine.

Does anybody know what the problem is? How can I make the list control to "hear" these SB_THUMBTRACK/SBTHUMBPOSITION messages?

Regards,
Asker.













0
Comment
Question by:asker
  • 4
  • 3
8 Comments
 
LVL 7

Expert Comment

by:galkin
Comment Utility
List control doesn't have child scroll bar. You can check it by Spy utility. It is rather drawing but not actual window. So it doesn't handle scrollbar messages. Use ScrollWindowEx to scroll list control.
0
 

Author Comment

by:asker
Comment Utility
To Galkin:

If a window is created with WS_VSCROLL/WS_HSCROLL it does not have a scroll bar control (it is only a drawing), but a window does receive WM_VSCROLL/WM_HSCROLL when you click it and you should handle them if you need to provide scrolling (read help on these messages).

By sending WM_VSCROLL message to the list control I simulate a situation when its own scrollbar gets accessed. When I am doing such with a list box or other controls (tree, for example. All of them do not have a scroll bar - use Spy++) - it works. It works with a list control - on line up/down, page up/down only. The question is - why sending SB_THUMBTRACK does not work with a list control while it works with the others?
0
 
LVL 11

Expert Comment

by:mikeblas
Comment Utility
Forcing fake WM_xSCROLL to any control or window is pure evil. You should, instead:

1) Find the correct programatic way to scroll the control. For a listbox control, you can use the LB_SETTOPINDEX message (or the CListBox::SetTopIndex() method in MFC). For a list view control, you should use the LVM_SCROLL (or the CListCtrl::Scroll() method in MFC) to scroll. Almost all controls have similar mechanisms.

2) Find the handle to the scrollbars on the control and call SetScrollInfo() on the scrollbar. In the SCROLLINFO structure, set the nPos member to be what you want. You might have to do a GetScrollInfo() first to get the other structure members.

.B ekiM

0
 

Author Comment

by:asker
Comment Utility
To Mikeblas:

>Forcing fake WM_xSCROLL to any control or window is pure evil.

Why? WM_xSCROLL messages are exactly what the control or window receives when the user works with a scroll bar. Each window handles those messages in a specific way, so instead implementing that processing once more (by myselsf), wouldn't it be better to send the WM_XScroll?

Scrollbar messages are just "interface" to the GUI element "scrollbar", which notifies its parent with them.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 11

Accepted Solution

by:
mikeblas earned 250 total points
Comment Utility
The WM_xSCROLL messages are what the window receives when the user scrolls, sure. But the semantics are very much different.

When the user scrolls, the control will have already updated the scrollbar info. When the control calls GetScrollInfo() in response to a WM_xSCROLL message, the info retruned will reflect the updated position and state of the scrollbar.

On the other hand, when you blindly send or post a WM_xSCROLL message, the information returned by GetScrollInfo() _hasn't_ been update. You're lying about the state change.

When you force a fake WM_xSCROLL message, you've not updated the scroll message.

It's naieve to think that messages are just an interface and can be forced and faked at will. The control is still quite free to alter its own state before or after the message is sent.

On the other hand, you're correct in pointing out that the WM_xSCROLL message is a notification of a change: it's invalid to send such a message when no state change occurs. By forcing the message, you're not causing the change--you're saying that a change has already occured.  And it hasn't.

I can tell you that, internally, the list view control (almost) immediately calls GetScrollInfo(). And your since your phony scroll messages arrive to the control without the scroll info changing, the control doesn't budge.  On the other hand, the list _box_ (not list _view_) control uses the messages to update the delta scroll for the window. It doesn't look at the scroll info; just the messages.

That explains the difference in behaviour between the controls, explain why your opinion that the messages are "an interface" is inaccurate, and why forcing fake WM_xSCROLL messages without updating the scrollbar info first is the work of Satan.

Did you even _try_ my suggestion of using LVM_SCROLL, by the way?

.B ekiM

0
 

Author Comment

by:asker
Comment Utility
To Mikeblas:

>I can tell you that, internally, the list view control (almost) immediately >calls GetScrollInfo(). And your since your phony scroll messages arrive >to the control without the scroll info changing, the control doesn't >budge.  On the other hand, the list _box_ (not list _view_) control uses the >messages to update the delta scroll for the window. It doesn't look at the >scroll info; just the messages.

That is the answer to my question, so I grade your answer. And I can guess why the situation is as such: the reason is 16 to 32 bit transition. WM_*SCROLL messages do not allow using of 32 bit nPos, nTrackPos and so on, so controls and windows have to use GetScrollInfo to get the correct message parameters. It means that SB_THUMBTRACK and SB_THUMBPOSITION messages should be considered as only notifications (in the common case) and their parameters should be ignored (only those returned from GetScrollInfo are valid).

So, if it were still 16 bit environment (without GetScrollInfo), my approach would work.

>Did you even _try_ my suggestion of using LVM_SCROLL, by the way?

No. I need a common solution, not that is control specific. And, please, believe me - I do not work for Satan, the only idol of mine is The User:-)

Thank you for the answer.

Regards,
Asker.
0
 
LVL 11

Expert Comment

by:mikeblas
Comment Utility
Forcing fake WM_xSCROLL messages may or may not work in any environment. 16-bit apps might call GetScrollPos() or GetScrollRange() instead of using the information provided with the control. Such an app, too, would fail when confronted with a phony scroll mssage.

.B ekiM

0
 

Author Comment

by:asker
Comment Utility
>Forcing fake WM_xSCROLL messages may or may not work in any >environment. 16-bit apps might call GetScrollPos() or GetScrollRange() >instead of using the information provided with the control. Such an app, >too, would fail when confronted with a phony scroll mssage.

No! GetScrollRange returns the range values - they are not changing while the thumb is being dragged (as a rule, of course), it does not return even the current position.

About GetScrollPos: here is what the help says about it:

" An application implements such scrolling by processing the WM_HSCROLL or WM_VSCROLL messages that carry the SB_THUMBTRACK notification message, thereby tracking the position of the scroll box, also known as the thumb, while the user moves it. Unfortunately, there is no function to retrieve the thumb’s 32-bit position while the user moves it. GetScrollPos provides static position data only; an application can therefore only obtain 32-bit position data before or after a scroll has taken place. "

It is not true - it is a mistake in the help (it is outdated!), because we know (thanks to you:-) that GetScrollInfo with SIF_TRACKPOS does return the 32 bit thumb position, while the current position of the scrollbar (retrieved with GetScrollPos or GetScrollInfo) DOES NOT CHANGE!

What does it mean? I believe, that earlier the only way to get the tracking position was to handle the parameter of the SB_THUMBTRACK message. That is why I belive that my approach would work in 16 bit environment (calling SetScrollPos with the tracking position and bRedraw = TRUE followed by immediate call to SetScrollPos with the original position and bRedraw = FALSE makes the scrollbar to move its thumb while keeping the current position constant).

Regards,
Asker.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Introduction: Dialogs (2) modeless dialog and a worker thread.  Handling data shared between threads.  Recursive functions. Continuing from the tenth article about sudoku.   Last article we worked with a modal dialog to help maintain informat…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

771 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now