"Win'98 like" Gradient Caption Bar

Environment: The demo project was created with Visual C++ 6.0. In order to run the compiled example (included) you need to have mfc42.lib version 6.0 or better. If you don't have it, you won't be able to run it. You must recompile the project.

This is how the window looks like when it's active.
This is how the window looks like when it's not active.

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.

const PAINTCAP& pc = *((PAINTCAP*)lParam);
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);
// Inactive caption
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;
r = r1 + (r2-r1)*(w-x)/w;

if (g1 > g2)
g = g1 - (g1-g2)*(w-x)/w;
g = g1 + (g2-g1)*(w-x)/w;

if (b1 > b2)
b = b1 - (b1-b2)*(w-x)/w;
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)

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.

if (GetLuminosity(clrFrom) > LUMINOSITY_MARK)

CFont* pOldFont = dc.SelectObject(&m_fontCaption);

// Restore DC

Visit my Internet Pages for updates and other articles.

Download demo project - 36KB

Date Last Updated: March 3, 1999