MFC Custom Color Caption Bar

Escher

Limp Gawd
Joined
Mar 9, 2000
Messages
496
I need a solution to the following problem: custom color the caption bar of an MDI application without using SetSysColor to override the system color set.

I've done the searching and seen code up on Code Project an the like that do an OK job of what I want, the problem is that most of it was never implemented or tested with WinXP Themes in mind and therefore breaks gloriously. I've tried tinkering with them in order to fix the problems, but can't get things like the Min/Max/Restore/Exit buttons to ever work or draw quite right. Either the XP buttons show up (which is ugly), or if I manually disable themes in the application, the buttons end up all jacked up as appear only half as wide as they should when you click on them.

It amazes me that there is no API to do this inherently in MFC, as it seems like it should be something fairly easy to do. SetSysColor works well enough, until you bring in the fact that it also changes the color of every other application as well. While you could caption OnActivate and switch back the colors to the system default, it's not very robust as the colors don't get reset when the application crashes or is terminated early while debugging.

Any help would be appreciated.
 
The reason MFC has no mechanism for this is pretty simple. We made the decision to stop adding things to MFC that would bloat its size and not be commonly used.

Microsoft doesn't encourage applications which use non-standard interfaces because that dilutes the value of Windows, which is based on the idea of an easy-to-learn, consistent UI. This reasoning is lost in the sands of time, as Microsoft itself continues to push non-standard user interfaces in its own products. But in the 90's, it was all the rage!

Adding the neccessary overrides to handle painting the non-client area is a slippery slope. MFC would have to start handling all those messages wherever they're sent, even if the application didn't handle them. Then, what features get implemented? Setting the font? Setting the background and foreground color? The transparency? The horizontal and vertical alignment? What about painting a graphic or a special font? An array of buttons?

Painting isn't as simple as drawing text, so these things all have to be considered. Then, people like you will want the same flexability and functionality for every Windows control and UI feature. This results in dozens of kilobytes of code that's generally not used by applications, not removable from applications which don't need it, and I decided it wasn't worth it to add to the library.

I hope that answers your soothes your surprise that MFC doesn't do this (or any number of other things).

Meanwhile, if you can clearly explain what it is you'd like to do, I might be able to help. Are you trying to change the color of the text, or the background? When a theme is applied, what do you specifically want to happen?
 
I'll take by your usage of "we" that you have had involvement with the development of MFC, which would be a good thing in my case.

All I want is to change the background color and thats it. MFC already provides a mechanism for painting buttons and such user defined colors, so at first glance what I want would seem to be trivial, after all it's just the color. When Themes are turned on, there's obviously problems, but we've already half-way worked around that by turning off Themes for the main application (child windows and dialogs still have Themes enabled, but that's ok).

So, simple problem (one would think) ... I want a custom color for the title/caption bar of the main application without having to call SetSysColors.
 
I'll take by your usage of "we" that you have had involvement with the development of MFC, which would be a good thing in my case.
Yes. I was on the MFC and ATL teams from 1992 through 1999. I wrote a couple of books about MFC, several magazines articles, and did countless presentations. When I left the team, I was the development manager.

So, simple problem (one would think) ... I want a custom color for the title/caption bar of the main application without having to call SetSysColors.
Just handle WM_NCPAINT for the window, and paint the appropriate area exactly the way you want it.
 
Problem then is the min/max/restore/close buttons. If I paint them myself, there are issues when Themes are turned on.

Such as, if Themes are on the system, the buttons are going to look goofy as I won't necessarily know what the theme looks like and therefore can't paint to match.

If I turn Themes off for the CMDIFrame (as I have right now), then my buttons look normal when painted, but when the user clicks, it turns out the real buttons are half the proper width and not located where I've painted.

I stated out using the CustomCaption project off of CodeProject and it worked fairly well, but had no real support for Themes. The caption bar painting looked fairly slick, but the buttons looked goofy with the incorrect background color.

If there was an API to allow the system to paint the buttons as it wanted, it might not act so goofy, but would still be mismatched colored with Themes turned on.

Hope I was clear enough. I'll try any solution presented (including the above).

Thanks!
 
It's been a while since I've wanted to write a non-standard application, but wouldn't you just call DrawFrameControl() with DFC_CAPTION? Once it does its work, you overdraw what you want differently with what you want different.

The thing is, in deciding to make a non-standard UI, you've also decided to fight an uphill battle. Windows isn't perfectly subclassable, and therefore there's no way to perfectly do (or not) certain actions in all circumstances.
 
I haven't seen that tactic before. Let me try it out and I'll get back to you.

Is there any chance you'd be willing to look at sample source and point out the flaws?
 
If you post your code here, I'm happy to help out as I have time. I'm sure other members will have a look, too.
 
Mike -

The base code I'm using comes from Code Project using this link: http://www.codeproject.com/gdi/customcaption.asp. Turns out it uses the method you described to draw the buttons. I've made some modifications as outlined in the posts to help resolve some of the issues with the buttons, but with no discernible effect.

Stick the following code into the InitInstance of your driver app to disable themes:
Code:
HINSTANCE hThemesDLL = AfxLoadLibrary("UxTheme.dll");
if(hThemesDLL)
{
    SETWINDOWTHEME lpfnSetWindowTheme = (SETWINDOWTHEME)::GetProcAddress(hThemesDLL, "SetWindowTheme");
    if(lpfnSetWindowTheme)
        lpfnSetWindowTheme(pMainFrame->m_hWnd, (L""), (L""));

    AfxFreeLibrary(hThemesDLL);
    hThemesDLL = NULL;
}
While this turns off Themes, it leaves the height of the caption wider than normal, which I wouldn't have expected, and that is probably the real root of the problem with the buttons, but I haven't been able to solve that either.
 
If you can provide your code, I can have a look when I have time.
 
Hey Mike! Thought you might have abandoned me. The link to the code I was attempting to use is a couple of posts above.
 
All I see is a link to the code you said you started with and modified.
 
That's about it. I created the default MFC MDI app and put that code I posted in the InitInstance to disable themes. Also, it does come with a demo app that demonstrates my frustrations with it nicely.
 
I'll see what I can do, but time is really scarce for me since we're in the middle of a big release.
 
Back
Top