Introduction
This is an update for the my article on colorizing the scrollbars of your window, that was posted long back in 2001. I do apologize that I took 5 years to comeback and update this article on CodeProject all at once. In the coming days, I am planning to upload a few more articles on this site on several different topics.
I was searching for a technique to colorize the scrollbars of the windows of my application so as to make the appearance of the UI a bit more attractive, especially the UI that I developed in VC++. As you know, to get anything done in MFC, you need to do a lot of circus. But, after all, we can find mountains of resources on the internet to help us do whatever we wish. That's what I did in order to bring this article very close to a beginner VC++ developer. I am going to show you how to get a scrollbar attached statically to an application's main window and more interestingly, how to colorize it.
Background [Technical details]
According to the MSDN, scrollbars let a user choose the direction and the distance to scroll through information in a related window. Scrollbars are of two types: horizontal and vertical. Now, let me introduce the components of a scrollbar. If we take up a standard vertical scrollbar, it has:
- The top arrow button
- The bottom arrow button
- The scroll box [also called as the scroll thumb]
- The scroll area where the thumb floats
To be precise, this article shows you how to colorize the fourth item of the scrollbar, that's the scroll area, and nothing else.
Using the code
Friends, we are going to attach our scrollbars to the main window frame of an SDI application and then we would see how to colorize hem. I would like to present the rest of the article in a tutorial style so that you could learn the concepts clearly, and then given a clue, you could also colorize the scrollbars of the child windows of an MDI app.
#1
Develop an MFC application of type Single Document Interface. Give a very nice name for the project as you wish, and accept all the default selections from the rest of the AppWizard and click Finish. After getting the skeleton code from the AppWizard, you will add some variables of type CScrollBar
in your frame class. This you can do manually as shown below.
class CMainFrame : public CFrameWnd
{
private:
CScrollBar myHScroll;
CScrollBar myVScroll;
CScrollBar myCutebox;
CBrush m_brColor;
...
...
};
#2
Now, create the scrollbars as usual after your frame is created in an OnCreate()
handler of the frame window class:
int CMainFrame::OnCreate(...)
{
......
......
CRect rect(0,0,0,0);
myHScroll.Create(WS_VISIBLE|WS_CHILD|SBS_HORZ, rect, this, AFX_IDW_HSCROLL_FIRST);
myVScroll.Create(WS_VISIBLE|WS_CHILD|SBS_VERT, rect, this, AFX_IDW_HSCROLL_FIRST+1);
myCutebox.Create(WS_VISIBLE|WS_CHILD|SBS_SIZEBOX, rect, this,-1);
m_brColor.CreateSolidBrush(RGB(255,0,0));
return 0;
}
As you can see in the above chunk of code, you also have to create a scrollbar box. This box is nothing but a little cute window that sits where the horizontal and vertical scrollbars meet each other.
#3
You also have to write code to keep resizing the scrollbars as and when you resize your window. This is being done in the overridden virtual function RecalcLayout(..)
, as shown below:
void CMainFrame::RecalcLayout(BOOL bNotify)
{
CFrameWnd::RecalcLayout();
CColorizedScrollsView* pView = (CColorizedScrollsView*)GetActiveView();
if (pView)
{
CRect rect;
pView->GetWindowRect(&rect);
ScreenToClient(&rect);
int cyHScroll = GetSystemMetrics(SM_CYHSCROLL);
int cxVScroll = GetSystemMetrics(SM_CXVSCROLL);
rect.right -= cxVScroll;
rect.bottom -= cyHScroll;
pView->MoveWindow(rect);
rect.left = rect.right;
rect.right += cxVScroll;
myVScroll.MoveWindow(rect);
rect.left = 0;
rect.right -= cxVScroll;
rect.top = rect.bottom;
rect.bottom += cyHScroll;
myHScroll.MoveWindow(rect);
rect.left = rect.right;
rect.right +=cxVScroll;
myCuteBox.MoveWindow(rect);
}
}
#4
And finally, the actual step to put the color into the scroll area. As this can only be done by handling the WM_CTLCOLOR
window message, a color notification is sent by every child window to its parent container window. Here it is:
HBRUSH CMainFrame::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
HBRUSH hbr = CFrameWnd::OnCtlColor(pDC, pWnd, nCtlColor);
if(nCtlColor==CTLCOLOR_SCROLLBAR)
return m_brColor;
return hbr;
}
#5
Don't forget to #include
the header files in the frame CPP file, that is in the MainFrm.cpp, say:
#include "ColorizedScrollsDoc.h"
#include "ColorizedScrollsView.h"
That's it. Compile and execute the code to get the colorized scrollbars displayed right there in your app's window.
Notes
- In this article, I have not discussed how the scrollbars work in order to scroll the contents. This is a kind of Doc/View topic. Basically, to put the scrollbars in action, you must handle the
WM_HSCROLL
and WM_VSCROLL
messages. It is left to you as an exercise.
- I promised above that I will give a clue to exercise this article on MDI applications. As you know, MDI contains the child frame windows within a main frame. So, the scrollbars would appear in the child frames instead of in the main frame. You just have to remember that whatever we did above in the main frame class, you will do the same in the child frame class instead. In addition, you have to remember two things. One is that the AppWizard doesn't automatically write the
OnCreate(..)
handler in the Child Frame class, you have to do it yourself. The second is that when you run the app, the scrollbars will not be seen anywhere. To get them shown, you have to maximize the child window. Or you have to handle the WM_SHOWWINDOW
message, and in that you have to say:
ShowWindow(SW_SHOWMAXIMIZED);
- I have provided the source code that can be either opened/compiled/executed by the MS VC++ 6.0 editor or by the MS Visual Studio .NET editor, as I have provided separate .dsp files and the .dsw file for the former and a .sln file for the latter.
- If you are VC++ 6.0 developer, you have to write the
WM_CTLCOLOR
message handler, its prototype, as well as an entry in the message map, all by yourself, because the Class Wizard doesn't list this message. You just copy the same from the sample code above into your frame class' header and the implementation files, respectively.
That's to say finished. Have a nice programming.....