"Win'98 like" Gradient Caption Bar
![]()
This article is based upon a previous article written by Brent Corkum called Gradient color caption bar. It brings additional features and fixes some of the problems. I modified the algorithm to display the window caption bar just like Win'98 does and I made it more user friendly. I have tested it in Win'95, Win'98 and WinNT.
Here are the features:
- You can specify the colors (the beginning and the ending color) of the gradient.
- Displays a gradient even when the window is inactive.
- Smoother gradient look.
If you want to implement this gradient bar in your project you probably need to see Brent's article first. If you already have seen his article then all you need to do to is replace the PaintMyCaption() method in your PaintCap.cpp file:
void CCaptionPainter::PaintMyCaption(WPARAM bActive, LPARAM lParam, CString m_strTitle)
{
if (lParam == 0) {
// lParam = 0 means system setting change:
invalidate fonts.
m_fontCaption.DeleteObject();
return;
}
const PAINTCAP& pc = *((PAINTCAP*)lParam);
ASSERT(pc.m_pDC);
CDC& dc = *pc.m_pDC;
int cxCap = pc.m_szCaption.cx;
int cyCap = pc.m_szCaption.cy;
COLORREF clrFrom; // the beginning color
COLORREF clrTo; // the ending color
// These are the default colors in Windows(R) 98
// Modify them to suit your needs.
if (bActive) {
// Active caption
clrFrom =
GetSysColor(COLOR_ACTIVECAPTION);
clrTo = RGB(16, 132, 208);
}
else
{
// Inactive caption
clrFrom =
GetSysColor(COLOR_INACTIVECAPTION);
clrTo = RGB(184, 180, 184);
}
// Get the intensity values for the ending color
int r1 = GetRValue(clrTo); // red
int g1 = GetGValue(clrTo); // green
int b1 = GetBValue(clrTo); // blue
// Get the intensity values for the begining color
int r2 = GetRValue(clrFrom); // red
int g2 = GetGValue(clrFrom); // green
int b2 = GetBValue(clrFrom); // blue
int x = 5*cxCap/6; // start 5/6 of the way right
int w = x; // width of area to shade
int xDelta= max(w/NCOLORSHADES,1); // width of one shade band
// Paint far right 1/6 of caption the background color
PaintRect(dc, x, 0, cxCap-x, cyCap, clrTo);
int r, g, b;
while (x > xDelta) {
x -= xDelta;
if (r1 > r2)
r = r1 -
(r1-r2)*(w-x)/w;
else
r = r1 +
(r2-r1)*(w-x)/w;
if (g1 > g2)
g = g1 -
(g1-g2)*(w-x)/w;
else
g = g1 +
(g2-g1)*(w-x)/w;
if (b1 > b2)
b = b1 -
(b1-b2)*(w-x)/w;
else
b = b1 +
(b2-b1)*(w-x)/w;
// Paint bands right to left
PaintRect(dc, x, 0, xDelta, cyCap, RGB(r, g,
b));
}
// Paint what's left of the caption with the beginning color
PaintRect(dc, 0, 0, x, cyCap, clrFrom);
// Use caption painter to draw icon and buttons
int cxIcon = DrawIcon(pc);
int cxButns = DrawButtons(pc);
// Now draw text. First Create fonts if needed
if (!m_fontCaption.m_hObject)
CreateFonts();
CString dt=GetDocTitle();
CString s;
// app title
if(dt.IsEmpty()) s = " " + m_strTitle;
else s = " " + m_strTitle + " - [" + dt +
"]";
CRect rc(CPoint(0,0), pc.m_szCaption); // text rectangle
rc.left += cxIcon+2; // start
after icon
rc.right -= cxButns; // don't
draw past buttons
dc.SetBkMode(TRANSPARENT); // draw on top of our
shading
// This is a trial and error value that sets the point
// where the caption background is too light/dark in
// order to display the text with white/black.
#define LUMINOSITY_MARK 120
if (GetLuminosity(clrFrom) > LUMINOSITY_MARK)
dc.SetTextColor(COLOR_BLACK);
else
dc.SetTextColor(COLOR_WHITE);
CFont* pOldFont = dc.SelectObject(&m_fontCaption);
dc.DrawText(s, &rc,
DT_LEFT|DT_VCENTER|DT_SINGLELINE|DT_END_ELLIPSIS);
// Restore DC
dc.SelectObject(pOldFont);
}
Visit my Internet Pages for updates and other articles.
Date Last Updated: March 3, 1999

Comments
To All Gurus
Posted by Legacy on 10/09/2001 12:00amOriginally posted by: Sudip
ReplyWhat about an SDI application?
Posted by Legacy on 04/10/2000 12:00amOriginally posted by: Jacques Cooper
Where does the "childframe" code go in an SDI application?
ReplyThe problem I am having may be related to the above question. I did not implement the "childframe" code and the minimize, maximize and cancel buttons only appear when I click on the title bar. I am using WinNT 4.0.
Problem with multi-threading
Posted by Legacy on 06/11/1999 12:00amOriginally posted by: johnnyboy
I found a strange problem that I'll try and progress, I've just put a very quick fix in. Basically, when my app invokes a viewer, which resides inside a COM object, the message loops appear to get mixed up - OnNcActivate in the CCaptionPainter is called from the other MainFame window. This at the very start of OnNcActivate() and OnNcPaint() solved the problem but it's not the most elegant solution:
if (m_pWndHooked != AfxGetMainWnd())
Replyreturn;
Working with dialog too?
Posted by Legacy on 05/12/1999 12:00amOriginally posted by: Paykan Imani
This is very good and worked fine.
I am searching the same but for Dialog.
How can i change your code to work with Dialog?
Regards
ReplyGradient Painting
Posted by Legacy on 03/04/1999 12:00amOriginally posted by: Tim Sooter
Your example clearly demonstrates how to provide a gradient look to a title bar, but what about painting a Cview in the same way. Do you have any examples of this?
ReplySmall Problem
Posted by Legacy on 03/04/1999 12:00amOriginally posted by: Keith Roberts
This class works great except for one small problem, when the window is active and you right click on the title bar and the system menu is shown, the area surrounding the three buttons on the right reverts to the win98 original colors.
Reply