Virtual Developer Workshop: Containerized Development with Docker

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


  • To All Gurus

    Posted by Legacy on 10/09/2001 07:00am

    Originally posted by: Sudip

    Well, Whta the fun in rediscovering the wheel and worse replicating it knowningly (I suppose I stopped short of saying some more). Peep into MSDN and the Guru of all gurus Paul Dilascia has an article 'ShadeCap'-- go through it. Its the best of all NcPaint jobs ppl have done here and there.. 

  • What about an SDI application?

    Posted by Legacy on 04/10/2000 07:00am

    Originally posted by: Jacques Cooper

    Where does the "childframe" code go in an SDI application?
    The 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 07:00am

    Originally 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())

  • Working with dialog too?

    Posted by Legacy on 05/12/1999 07:00am

    Originally 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?


  • Small Problem

    Posted by Legacy on 03/04/1999 08:00am

    Originally 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.

  • Gradient Painting

    Posted by Legacy on 03/04/1999 08:00am

    Originally 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?

  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date