There are two types of scrollbars


Remember that there are two types of scrollbars.

One is the standalone scrollbar control. This one has its own window handle, and consequently can be given focus and all those other fun things you can do with window handles. To manipulate them, pass the handle to the scrollbar control to the appropriate scrollbar function (SetScrollInfo, for example) and pass SB_CTL as the nBar parameter to indicate that you have a scrollbar control.

The other type is the horizontal or vertical scrollbar (or both) attached to a window by virtue of having the WS_HSCROLL and/or WS_VSCROLL style. These are nonclient scrollbars and are not controls. They are just decorations added to some other window. You can't give them focus since they aren't windows in their own right. To manipulate them, pass the handle to the containing window to the appropriate scrollbar function and pass SB_HORZ or SB_VERT as the nBar parameter to indicate that you want to manipulate the nonclient horizontal or vertical scrollbar.

I'm writing this down since some people seem to miss the distinction between these two cases.

Comments (26)
  1. asdf says:

    Is there any way to tell if a window’s scrollbars are disabled given an HWND and either SB_VERT or SB_HORZ (by disabled I mean the scrollbar is visible and looks like a SB_CTL drawn with WS_DISABLED)?

  2. Raymond Chen says:

    This is just an exercise in logic. Nothing magic going on here. People should be able to figure this out on their own.

    http://msdn.microsoft.com/library/en-us/shellcc/platform/commctls/scrollbars/aboutscrollbars.asp – Scrollbar Visibility – a nonclient scrollbar with no valid range is automatically hidden (or disabled if you say SIF_DISABLENOSCROLL). So if the scrollbar range is invalid, and the scrollbar is visible, then it must be disabled.

  3. jeffdav says:

    Ah, but there is a third type of scroll-bar; the scroll-bars mshtml draws for Web pages.

  4. CW User says:

    Hi,

    Maybe I am not on target, but few days ago I just started thinking

    about control IDs of "complex" controls, like IDs of scrollbars within

    lists and IDs of lists within combo boxes.

    So I did two things. First I had a look into WINE and there it was,

    list in combo has a fixed ID of 1000. Then I put some checks in

    WndProc to see if I am getting WM_COMMAND for that ID and

    everything seemed just fine, but I am still not convinced 100%.

    Is there a document on web where these things are explained?

  5. Raymond Chen says:

    The internal structure of complex controls is internal and subject to change at any time. It’s called "encapsulation".

  6. CW User says:

    So I shouldn’t worry about it and can forget parts of these controls

    may have their own IDs. Thank you!

  7. Tom Seddon says:

    Yes, the scroll bars on web pages are interesting. I tried spying them with Spy++, but no messages ever got sent — either they work by magic :) or Spy++ ignored the relevant window messages. I assumed the former.

  8. Raymond Chen says:

    They aren’t windows. They are HTML objects. You can use accessibility to get to them.

  9. asdf says:

    That only works if your scrollbar is disabled that way and not via EnableScrollBar. The way to do it is with the super hidden similarly named GetScrollBarInfo function. Except this doesn’t work in Windows 95 or on NT4 with a service pack earlier than 6.

  10. Raymond Chen says:

    Ah true about EnableScrollBar. GetScrollBarInfo is an accessibility function.

  11. Presentation Manager sure did a nice job of cleaning up these warts. PM windows did not have client and non-client areas. All of the gizmos that go in the non-client area in Windows were simply child windows. The client rectangle was another child window. All these special cases, all of the WM_NCxxxx messages went away. It was a *much* cleaner architecture.

    Ah well, can’t change history…

  12. Serge Wautier says:

    Raymond,

    (Kind of bouncing on Michael Geary’s comment.)

    Could you some day write about the reasons that led the Windows team to develop the concept of non-client area. e.g. Why aren’t all NC parts simple child windows ? Or why isn’t the client area a child window itself ? Did you guys develop the concept because of flaws found in the OS/2 architecture ?

    TIA.

  13. Serge Wautier says:

    Raymond,

    (Kind of bouncing on Michael Geary’s comment.)

    Could you some day write about the reasons that led the Windows team to develop the concept of non-client area. e.g. Why aren’t all NC parts simple child windows ? Or why isn’t the client area a child window itself ? Did you guys develop the concept because of flaws found in the OS/2 architecture ?

    TIA.

  14. Raymond Chen says:

    Windows predates OS/2; OS/2 was a reaction to Windows and not vice versa.

    Remember that Windows originally had to run in 640K of memory and that all USER data (windows, menu, accelerator tables…) had to fit into 64K ("system resources"). If a window is around 200 bytes (just guessing) then that means at most 300 windows in the system – and that’s if you promise not to have any menus! If the nonclient area consisted of windows too, then a simple frame window would actually be 5 windows (frame, system button, minimize button, maximize button, client area), which brings you down to 60 windows before you ran out of memory.

    I think everyone can agree that a maximum of 60 windows is woefully inadequate. Heck, Calc in scientific mode is already 70 windows!

  15. Ben Hutchings says:

    So why is every control a window, apparently a fairly heavyweight object?

  16. Raymond Chen says:

    Not every control is a window. There’s a whole world of windowless controls out there.

  17. Mike M says:

    I have a question which pertains to scrolling. I don’t know if this is the best place to ask, but I been trying to wrap my brain around the inner workings without success; so here it goes…

    How does the header control remain stationary on list control (report style) despite vertical scrolling? I am trying to implement my own custom drawn view (CScrollView) with header like control, but my header always moves during vertical scrolling, unlike the CListCtrl’s header.

  18. Raymond Chen says:

    Vertical scrolling doesn’t move anything. It just tells the listview control "The user moved the scrollbar. Do whatever you think is appropriate." In listview’s case, it decides "Okay, well now I’ll draw those items in different places." It doesn’t move the header control.

    I don’t know what CScrollView is, but from its name I’m guessing that it is a pre-written scrolling viewer that just moves *everything* in the view when you scroll. Which is not what you want.

  19. Raymond Chen says:

    Run Spy and find out.

  20. Alexandru says:

    But surely, internally the vertical/horizontal scrollbars *are* child windows?

    Since they look and act exactly the same as the scrollbar controls?

    Or is it the other way around — scrollbar controls are implemented "in terms of" their non-window counterparts?

  21. Alexandru says:

    I meant deeper down "internally", beyond window handles.

    Never mind. :)

  22. Raymond Chen says:

    Internally they are what you see: Built into the window frame. They are not child windows.

  23. Dru says:

    Raymond, can you elaborate more on "Windowless Controls" and the controls in IE. Did MS duplicate all of that functionality in IE as a separate code baase (checkboxes, listboxes, editboxes, buttons, radio buttons, etc??)

  24. Raymond Chen says:

    You’d be better off asking somebody who works on IE. Windowless controls have been around for a long time. They are particularly important for IE to avoid draining the desktop heap when a web page has, say, 5000 checkboxes on it. But I should let an IE person discuss it; I’m talking from general principles.

  25. Raymond Chen says:

    Commenting on this article has been closed.

Comments are closed.