Setting thumb color also has effect of enabling display of
thumb color. The channel color is enabled by default, and will be displayed
if thumb color is enabled.

CreateFromRect()

In case it is not convenient to create a placeholder window, you can also
create XScrollBar control by specifying rect:

//=============================================================================//// CreateFromRect//// Purpose: Create the CXScrollBar control from rect//// Parameters: dwStyle - the scroll bar’s style. Typically this will be// SBS_HORZ|WS_CHILD|SS_LEFT|SS_NOTIFY|WS_VISIBLE.// pParentWnd - the scroll bar’s parent window, usually a CDialog// object. It must not be NULL.// rect - the size and position of the window, in client // coordinates of pParentWnd// nId - the resource id of the CXScrollBar control//// Returns: BOOL - TRUE = success//

Implementation Notes

XScrollBar Component Structure

The diagram below shows the components of an XScollBar,
and the nomenclature that will be used in this article:

As you probably guessed, the XScrollBar is drawn in five steps
(six, if you count the border). The drawing takes place
in DrawHorizontal() function.

Drawing the XScrollBar: Step 1 - Left Arrow Button

The left arrow button bitmap looks like
this (the orange border is not part of the bitmap):

One thing to note is that arrow bitmaps and thumb bitmap are assumed to
be all the same size, which simplifies some calculations. The size of the
thumb bitmap (m_nBitmapWidth, m_nBitmapHeight) is set in the
CreateFromStatic() function.

Knowing that width of the left arrow bitmap = width of the thumb
bitmap, we can write

StretchBlt() is then called to copy the left arrow bitmap into
the memory DC, and a border is drawn around the left arrow. Note that the
bitmaps do not include a border, because StretchBlt()
may decide to duplicate the row that contains the border, and you will
end up with a thick line on the bottom.

Drawing the XScrollBar: Steps 2 & 3 - Channel

Next we draw channel. In case a color is being displayed in the channel,
it must be drawn in two parts. Because we modify the bitmap to add color,
we draw the right channel (the part without color) first.

The channel bitmap is one pixel wide and looks like
this (the orange border is not part of the bitmap):

StretchBlt() is then called to copy the right channel bitmap into
the memory DC.

If a thumb color and channel color (both are required) are desired,
then we must modify the channel bitmap to add color. But what color to use?
Here is where Christian Rodemeyer's CColor class comes in.
We use CColor to convert the RGB thumb color to HLS,
and then lighten the color by adjusting the HLS values. Finally, we
convert back to RGB, and this is new channel color.

StretchBlt() is then called to copy the left channel bitmap into
the memory DC

Drawing the XScrollBar: Step 4 - Right Arrow Button

The right arrow button bitmap looks like
this (the orange border is not part of the bitmap):

The right arrow button is drawn much like the left arrow button.

Drawing the XScrollBar: Step 5 - Thumb

The thumb bitmap (for a thumb with no color) looks like this:

For a thumb with color it looks like:

The thumb bitmaps are modified before being drawn to the memory DC.
For a thumb with no color, the only modification that may be necessary
is to replace the thumb gripper pixels with pixels taken
from the surrounding area on the thumb, thus making the gripper disappear
(how this is done will be explained below).

For a thumb with color, in addition to the gripper pixels, it is
also necessary to make the corner pixels transparent (i.e., same
color as channel). and to add the selected thumb color (or hover color).
All these changes are accomplished by using four "special" RGB color values:

This technique for coloring the thumb and channel works for True Color
(24-bit). Lower resolutions may require you to use other RGB values
for the four "special" RGB thumb colors, and it may also require
that you limit the color used in the channel.

Mouse Hover

A final thing to take care of is when the mouse hovers over the thumb.
In this case, the thumb color will be changed to the hover color
(as seen in the above code),
and the cursor will be changed to a hand:

This is handled in the OnSetCursor() function.

How To Use

To integrate XScrollBar into your app, you first need
to add following files to your project:

XScrollBar.cpp

XScrollBar.h

Color.cpp

Color.h

memdc.h

Next copy the bitmap files
to the project's res directory, and add the bitmaps to the .rc file.
I find it easiest just to edit the .rc file manually:

I used
HPS PixelColor to capture screen colors and inspect
the scroll bar on the screen.

I used Impict, which ships with
Help & Manual,
to annotate the images.

Revision History

Version 1.2 - 2008 August 29

Optimized bitmap loading

Changed to CWnd

Added hot state to arrows and thumb (no color)

Added pressed state to arrows

Focus shown by hot state of thumb

Added CreateFromWindow() and CreateFromRect() functions

Removed CreateFromStatic()

Added GetScrollRange()

Added keyboard input

Version 1.1 - 2004 September 21

Update with Steve Mayfield's vertical scroll bar implementation.

Version 1.0 - 2004 September 9

Initial public release.

Usage

This software is released into the public domain. You are free to use
it in any way you like, except that you may not sell this source code.
If you modify it or extend it, please to consider
posting new code here for everyone to share. This software is provided
"as is" with no expressed or implied warranty. I accept no liability
for any damage or loss of business that this software may cause.

Share

About the Author

I attended St. Michael's College of the University of Toronto, with the intention of becoming a priest. A friend in the University's Computer Science Department got me interested in programming, and I have been hooked ever since.

Recently, I have moved to Los Angeles where I am doing consulting and development work.

For consulting and custom software development, please see www.hdsoft.org.

Comments and Discussions

is there a possibility to change the thumb and channel color at runtime?
I want to show critical values by changing the channel + thumb color to red.
I tried it with SetThumbColor.
Effect: The channel changes its color, but not the thumb. When I move the mouse over the ScrollBar, it changes the color back to the original color.

There are two colors involved - the normal color and the hover color. If you call SetThumbColor(), this changes the normal color. Currently, SetThumbColor() works correctly and the non-hover (normal) thumb color will be changed.

However, the same is not true for SetThumbHoverColor(). It is missing a call to LoadThumbBitmap(). Here is the fixed function: