Recently, I was implementing a PropertySheet based wizard, and part of the graphic design was to place a bitmap as the window background and then draw the text and other controls over that. I found a few examples of using a bitmap as a dialog background - the best of which simply involved overriding the default
That worked fine, but of course, the Static text controls were still being drawn on their beige backgrounds. I found a couple of ideas about drawing transparent text, but they generally involved overriding
WM_PAINT and doing all the text drawing yourself. I was hoping for something simpler.
There are numerous articles about overriding
WM_CTLCOLOR, and they generally discuss using this as a way to change the text color or the background color. I was put off for a long time by the name '
WM_CTLCOLOR' thinking that it was just about color. However, you can change several characteristics of the drawing environment here just before a control is drawn.
It is possible to call
SetBkMode and set the background mode to
TRANSPARENT which keeps the text drawing routines from erasing before drawing text. This is not quite enough however because when a Static control is drawn, the entire control background is first painted with the
HBRUSH returned by
OnCtlColor. Fortunately, having
OnCtlColor return the
NULL_BRUSH takes care of this as well.
Using the code
This example implements a PropertySheet based wizard. The same techniques would apply to a Dialog.
To change the
CStatic text behavior to transparent drawing requires adding one message handler with four lines of code.
I create a sub-class of
CPropertyPage (for a regular dialog, you would create a sub-class of
CDialog). Then I use ClassWizard to create a handler for
WM_CTLCOLOR. In that handler,
OnCtlColor, I check the
nCtlColor parameter, and if it shows that we are about to draw a Static control (
CTLCOLOR_STATIC) then I call
SetBkMode to change the DC mode to
TRANSPARENT. I also get a handle to the stock
NULL_BRUSH object and return that as the function result. Then Windows takes care of all the text drawing itself.
You can change a number of things about the DC in
OnCtlColor. All of the various CDC functions are available such as
SetTextColor which allows you to change the text color. Of special note is the ability to use
CDC::SelectObject which allows you to change the Pen, Brush, Font, Bitmap and Region. The ability to modify the font here is especially useful in working with PropertySheets because there is no way to set the face, size, or style of the font used (PropertySheets always use MS Shell).
This example also implements using a bitmap for the dialog background. This is done by using ClassWizard to create a handler for
WM_ERASEBKGND in the
CDialog) sub-class. The
OnEraseBkgrnd routine then fills the window with the bitmap instead of painting with the background brush.
- 1.0 -15 Jul 2004 - first version.
Software engineer working on commercial applications used in color management.