Download full source (79Kb)
Download demo executables (standard and MFC)
(65Kb)
Cool Scrollbars is a library I have written to customize the standard scrollbars of a window. Please note that this library only supports standard window-scrollbars. Separate scrollbar controls are NOT supported. If you want to customize a scrollbar control, then you must devise your own method.
Rather than explain how this library works, I will describe how to use the library in your applications. Cool scrollbars behave exactly like normal scrollbars in a window. However, unlike standard scrollbars, cool scrollbars can be heavily customized. The library is written entirely in the C programming language, and can be compiled to a tiny 14kb! With all features enabled, this rises to around 20kb. This is a pretty small overhead for something which is so complex. Although this library does not require any external libraries such as MFC, ATL, WTL etc, there is NO reason why you cannot use this library in those types of project.
Starting with version 1.1 of the Cool Scrollbar library, is a new feature which makes it possible to add cool scrollbars to any window in your program, even if you don't have access to the source-code. This includes standard Windows Controls (edit, list-boxes) and the Common Controls (ListView, TreeView etc).
Unfortunately this feature is only available when a program is running under Windows NT, 2000 and XP. This is because of the different ways the Windows 9x and NT operating systems map DLLs into a process's address space. This difference prevents a process from hooking API calls when running under Windows 9x, and is the reason why this feature is only available under NT.
Perhaps a later version of the Cool Scrollbar library will address this problem. Until then however, a program which must run under Windows 95,98 or ME is restricted to having cool-scrollbars only on windows for which the source-code is available.
The Cool Scrollbar download now contains an additional library which provides a program with the ability to enable cool-scrollbars for ANY window in that program. This library (coolsb_detours) uses a technique called binary-rewriting to hook and intercept all of the standard scrollbar API calls inside USER32.DLL. The coolsb_detours library actually relies on the superb Detours package available from research.microsoft.com.
In order to use coolsb_detours, you must goto Microsoft's research site and download the Detours package. There is only one file you actually need, but the Detours license agreement prevents me from distributing this file myself. You can goto the Detours page here:
http://research.microsoft.com/sn/detours
The only file you need from this package is "lib\detours.lib". Simply copy this file into the coolsb_detours directory before you try to compile it. Please read Microsoft's licence agreement for this package before you start - it contains some important information.
Once you have downloaded the Detours package you must add the coolsb_detours project to your workspace, as well as the standard coolsb project. You do not have to include coolsb_detours if you don't need the new feature it offers.
There are two new cool-scrollbar API calls which enable and disable support for all types of window.
BOOL CoolSB_InitializeApp(void);
CoolSB_InitializeApp allows your program to apply cool-scrollbars
to any window created by your program. Note that CoolSB_InitializeApp
does not enable the cool-scrollbars themselves - this is still achieved with
the InitializeCoolSB API call (see below). You would typically
call CoolSB_InitApp at the start of your program.
BOOL CoolSB_UninitializeApp(void);
CoolSB_UninitializeApp must be called before your program exits
(assuming that you also called CoolSB_InitializeApp)
These two functions will only return successfully when a program is running under Windows NT, 2000 or XP.
To add cool scrollbars to a window, call InitializeCoolSB, passing
the handle to the window. Unless you are using the coolsb_detours package
under Windows NT/2000/XP, you must replace ALL standard scrollbar functions,
such as SetScrollInfo or GetScrollInfo, with the
equivalent CoolSB_xxx version. There is a cool scrollbar function
call for every standard scrollbar API call. These functions behave in the exact
same way as the standard API calls. If cool scrollbars haven't been enabled for
a window, the cool scrollbar functions will default to the standard API calls
automatically. This allows you to turn cool scroll bars on and off without
having to write conditional code.
In addition to the standard scrollbar functions, cool scrollbars offer a number of extra features, and also a set of API calls to manipulate these features.
Note: You do NOT need to use the CoolSB_xxx scrollbar
functions if you are using the coolsb_detours library.
CoolSB_SetSize allows to alter the size of either the horizontal
scrollbar, or the vertical scrollbar, or both. You should be very sure that you
really want to change the size of a scrollbar, because it could annoy a user
who has set their system scrollbar sizes to the exact size that they want.
BOOL CoolSB_SetSize(HWND hwnd, int wBar, int nLength, int nWidth);
By using this API call, you can alter the two dimensions of a scrollbar.
SB_HORZ, SB_VERT
or SB_BOTH.
By specifying a non-negative integer number, you can specify the size, in
pixels, of a scrollbar arrow. The scrollbar size will remain unaffected by the
system scrollbar settings, even if the user changes these settings whilst your
program is running.
Important. By specifying a negative number, you can set the scrollbar
dimensions to a multiple of the system scrollbar sizes. A value of -1 or SYSTEM_METRIC
results in scrollbars which are the exact same size as a normal scrollbar. A
value of -2 results in scrollbars twice the size of a standard scrollbar, and
so-on. By using negative values, the cool scrollbars will always be sized
according to the system scrollbar metrics. You do not have to call this
function every time the scrollbar system metrics are changed by the user.
You should try to assign the same number to both the length and the width. If you use different values, then your scrollbars will looked squashed in one dimension.
The Cool Scrollbar library supports Flat scrollbars, like the variety found in the common controls library. Unlike the Microsoft flat scrollbars, the cool scrollbars only support two types of flat scrollbars. These are standard flat-looking scrollbars, without "hot-tracking", and normal flat scrollbars, with "hot-tracking" enabled. Hot-tracking is the feature that highlights a portion of a scrollbar when the mouse moves over it.
The CoolSB_SetFlatMode API allows you to give a cool scrollbar
enabled window flat scrollbars.
BOOL CoolSB_SetFlatMode(HWND hwnd, int wBar, UINT nFlatMode);
You must specify which scrollbar of a window will be displayed as a flat
scrollbar, by using the wBar parameter. This can be either SB_HORZ,
SB_VERT, or SB_BOTH if you want both scrollbars to
become flat looking. The nFlatMode parameter can be one of three values.
| CSBS_FLAT | Normal looking flat scrollbars |
| CSBS_HOTTRACKED | Hot-tracked flat scrollbars |
| CSBS_NORMAL | Remove the flat look |
There are four functions available to insert a button into a scrollbar. You can insert buttons to the left or right of a horizontal scrollbar, and above or below a vertical scrollbar.
All of these functions use the SCROLLBUT
structure to specify the attributes of each button. You must use the fMask
member to specify which members of the SCROLLBUT structure contain
valid information.
BOOL CoolSB_InsertButton(HWND hwnd, int wSBflags, UINT nPos, SCROLLBUT *psb);
SB_HORZ or SB_VERT
SCROLLBUT structure which specifies
the button properties.The remaining button functions all deal with buttons that are already inserted into a scrollbar.
BOOL CoolSB_ModifyButton(HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd, SCROLLBUT *psb); BOOL CoolSB_RemoveButton(HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd); BOOL CoolSB_GetButton (HWND hwnd, int wSBflags, UINT uItem, BOOL fByCmd, SCROLLBUT *psb);
SB_HORZ or SB_VERT
TRUE, then uItem is the command
identifier of the button, which is specified by the uCmdId member of the
SCROLLBUT structure when a button is inserted.FALSE, then uItem
is a non-negative integer specifying the position of the button to modify /
remove.
SCROLLBUT structure.Inserted buttons will receive mouse click notifications The NM_CLICK
message will be sent for mouse-down events, and the normal WM_COMMAND
message for mouse-up events. The NM_CLICK message (sent in the
form of a WM_NOTIFY) uses the NMCOOLBUTMSG
structure, which contains useful information such as the coordinates of the
button.
When COOLSB_TOOLTIPS is defined in the userdefs.h file, tooltip
notifications will be sent to the window if the mouse hovers over one of the
inserted buttons. By ignoring these messages, tooltips will not be displayed.
However, by handling the WM_NOTIFY message correctly, it is simple
to add tooltips to any of the inserted buttons.
You only need to respond to the standard TTN_GETDISPINFO notification
in order to display a tooltip. The button's command identifier will be
specified in the hdr.idFrom member of the NMTTDISPINFO structure.
Below is the sample code required to support tooltips.
case WM_NOTIFY:
{
NMTTDISPINFO *ttdi;
ttdi = (NMTTDISPINFO *)lParam;
if(ttdi->hdr.code == TTN_GETDISPINFO)
{
wsprintf(ttdi->lpszText, "This is button %d", ttdi->hdr.idFrom);
ttdi->hinst = hInst;
}
return 0;
}
The cool scrollbar library supports a subset of Custom Draw, the feature found with many of the common controls shipped with Windows. Custom Draw allows an application to completely take over the drawing of a window's scrollbars, and replace the scrollbar graphics with a completely user defined look.
Just like the standard Custom Draw facility, drawing requests are sent to a cool
scrollbar enabled window via a WM_NOTIFY message.
A NMCSBCUSTOMDRAW structure is used to notify you of drawing operations.
Not all of the Custom Draw functionality is implemented for cool scrollbars.
Only three notifications will be sent to a window - CDDS_PREPAINT (to
check if you want to custom draw or not), CDDS_POSTPAINT (after
drawing has finished) and CDDS_ITEMPREPAINT, for each scrollbar
item. A pre-paint and post-paint notification is sent one for each scrollbar,
whenever it needs to be painted. These two notifications are not sent when the
scrollbar gripper (the dead area) needs to be painted; only an item pre-paint
is sent in this case.
It is important to note that the return value from the CDDS_ITEMPREPAINT
notification is not currently used. It is assumed that if custom draw is
enabled (by returning CDRF_SKIPDEFAULT in the pre-paint step),
then the whole scrollbar will be custom-drawn, so you must draw all portions of
a scrollbar if you want to draw any at all.
If for some strange reason you want to turn off cool scrollbars, then simply
call the UninitializeCoolSB API, passing the handle to the window.
You do not need to call this function when your window is destroyed, as the
cool scrollbars will automatically remove themselves in this instance.
This library is written entirely in the C language, and uses no other library other than the standard win32 API. In order to encapsulate the code, it was necessary to package all of the implementation code into a single file, with all functions given static linkage so they don't conflict with other functions in your projects. This is a drawback of using C. It would be better to split the source into separate files which deal with specific scrollbar functions - such as drawing code in one file, mouse code in another and so on. However, this would require the use of namespaces to encapsulate the library, and namespaces are only available in C++. I thought that reaching a wider audience was more important in this case, but feel free to use your C++ compiler instead.
I should also take this opportunity to defend my use of C++ style comments in a C project. My reason: I find it tedious to use the C-style comments. Also, every C compiler for Windows that I tried accepts C++ comments with no problem. In fact, the new C99 standard allows the use of C++ style comments, but the project will compile fine on older compilers also. So there.
IMPORTANT:
There is a file called userdefs.h which can be used to include or
exclude certain features of the cool scrollbar library. If you don't want
support for inserted buttons, for example, then you can #undef the
INCLUDE_BUTTONS definition, which will result in a smaller code
size. There are many features which can be altered in this way, and they are
all fully documented in this file.
(Only relevant under Windows 95,98,ME)
Someone is bound to complain that they can't add cool scrollbars to a tree-view control, or an edit control, so I'll explain why this isn't possible.
Firstly, it is quite possible to custom-draw the scrollbars on a standard
window. All you need to do is call InitializeCoolSB, after all.
However, internally, the standard windows all make use of the standard
scrollbar functions such as SetScrollInfo and SetScrollPos.
This is a problem, because these functions cause a window's scrollbars to be
re-drawn, and this redraw does not get performed via a WM_NCPAINT message.
Whenever you resize a standard window, or scroll up and down in one, the
standard scrollbar API will be called, and this will cause your nicely drawn
custom scrollbars to be over-written. So, unless you have the source-code to a
window or control, you cannot apply the cool scrollbar library to it, because
you must call the CoolSB_xxx API functions to perform all
scrolling operations instead.
Still not convinced? Well, in theory there is a way to overcome these problems
and use the coolscrollbar library on any window, but it is not for the
feint-hearted. It is possible to intercept any Windows API call in a program,
and perform such tasks as replacing the function call with another user-defined
call. For example, you could intercept all scrollbar API calls that your
program made, and forward them on to the CoolSB_xxx versions
instead.
There are loads of sources on the net which do API interception. These are the two techniques that I would look at:
CoolSB_xxx
functions.
The new coolsb_detours library uses the second technique above to overcome this problem, but this will only work when your program runs under Windows NT. If you are using the Windows 9x family of operating systems, then your are on your own.
The Cool Scrollbar library is now in it's second release (version 1.1). Although I have addressed a couple of minor problems and introduced some new features, you must still be careful when you use this library. There might be bugs or incompatibilites with your projects which I have over-looked. I've tested the library thoroughly with my own projects, but it remains to be seen whether I've got it completely right. Feedback would be appreciated!
Please send any comments or suggestions to:
Last modified: 16 February 2005 20:02:27