Date: | April 20, 2005 / year-entry #99 |
Tags: | code |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20050420-28/?p=35843 |
Comments: | 21 |
Summary: | The DC brush GetStockObject(DC_BRUSH) is a stock brush associated with the device context. Like the system color brushes, the color of the DC brush changes dynamically, but whereas the system color brushes change color based on the system colors, the color of the DC brush changes at your command. The DC brush is handy when... |
The DC brush
The DC brush is handy when you need a solid color brush for
a very short time, since it always exists and doesn't need to be
created or destroyed. Normally, you have to create a solid color brush,
draw with it, then destroy it. With the DC brush, you set its color and
start drawing.
But it works only for a short time, because the moment somebody else
calls
the The DC brush is amazingly useful when handling the various WM_CTLCOLOR messages. These messages require you to return a brush that will be used to draw the control background. If you need a solid color brush, this usually means creating the solid color brush and caching it for the lifetime of the window, then destroying it when the window is destroyed. (Some people cache the brush in a static variable, which works great until somebody creates two copies of the dialog/window. Then you get a big mess.) Let's use the DC brush to customize the colors of a static control. The program is not interesting as a program; it's just an illustration of one way you can use the DC brush. Start, as always, with our scratch program, and making the following changes. BOOL OnCreate(HWND hwnd, LPCREATESTRUCT lpcs) { g_hwndChild = CreateWindow(TEXT("static"), NULL, WS_VISIBLE | WS_CHILD, 0, 0, 0, 0, hwnd, NULL, g_hinst, 0); if (!g_hwndChild) return FALSE; return TRUE; } HBRUSH OnCtlColor(HWND hwnd, HDC hdc, HWND hwndChild, int type) { FORWARD_WM_CTLCOLORSTATIC(hwnd, hdc, hwndChild, DefWindowProc); SetDCBrushColor(hdc, RGB(255,0,0)); return GetStockBrush(DC_BRUSH); } HANDLE_MSG(hwnd, WM_CTLCOLORSTATIC, OnCtlColor); Run this program and observe that we changed the background color of the static window to red.
The work happens inside the The static control then takes the brush we returned (the DC brush) and uses it to draw the background, which draws in red because that's the color we set it to. Normally, when customizing the background brush, we have to create a brush, return it from the WM_CTLCOLORSTATIC message, then destroy it when the parent window is destroyed. But by using the DC brush, we avoided having to do all that bookkeeping.
There is also a DC pen |
Comments (21)
Comments are closed. |
Raymond are you not contradiciting yourself?
> In practice, this means that the DC brush color is not trustworthy once you relinquish control to other code
Well, when your code returns you lost control.
Another words where is the guarantee that control uses your brush right away?
The trouble is that Windows doesn’t support the stock DC brush. Only certain specific versions of Windows support it.
In a corporate context that’s OK because you have some control; but in the wider world you can’t go excluding people from your market like that, so you have to have code that handles the other versions anyway.
If every DC has a DC brush, how does GetStockObject(DC_BRUSH) know which one to return? Does it really just a return a magic handle value which the SelectObject call knows about?
Universalis: True, if you need to run on Windows 98, then you can’t use this.
Adrian: GetStockObject(DC_BRUSH) returns the DC brush. The DC brush doesn’t have a color itself; it takes its color from the DC. That’s the whole point of the DC brush.
Will this also work in metafiles?
Raymond> I think the question was how does GetStockBrush(DC_BRUSH) know which DC you mean, since there is no HDC parameter?
Simon Cooke> You bet I’m still supporting Win 98 and Me. The people who buy my software still use 98, and I sure as hell am not going to give up sales (meaning, lose money) by supporting only 2K+.
Only about 5% of PC users use Windows XP. Similar proportions for 2000, NT4, and 98.
The remaining 80% of PC users use Windows.
… of course, if you’re still supporting Windows 98 today, 7 years after it came out, I feel for you, I really do.
Still, at least you’re not supporting Windows ME, right? *evil grin*
It’s magical in a similar way that monochrome DDBs use the BkColor and TextColor of the DC it’s selected in as their palette as opposed to monochrome DIBs that use a palette stored in the bitmap header. GDI has all sorts of neat tricks like this hidden that not many people seem to know about (another one is that you can get the stock 1×1 monochrome bitmap handle by passing a 0 width or 0 height to certain bitmap creation functions).
Unfortunately most of people give up 98 – including Microsoft, Matrox, freeware coders – no support, no drivers, even no apps anymore. I hate situation when I can’t use some software because one feature of XP, which could be, rather, easily implemented or just skipped, as unnecessary, under 98 – either by app’s coder or Microsoft. I.e. GUI+ and some of statistics functions – maybe it’s harder but in my opinion it needs only some exports [at least w/ faked, nearly empty functions] and modifications of blits. I.e. alpha effects could be done by simple, imperfect trick like that one used by Avast!. Then you get uprising compatibility and functionality.
Hmmm… Maybe it’s time to get my hands on such things :) .
Adrian, why would Microsoft want to do the harder work to support Windows 98? They would rather you buy a new OS from them, and this is one way they can subtly apply pressure on you to do it. Obsolescence is not a feature of software, but you can build it in if you have a dominany market position.
Moi: If you want to continue supporting Windows 98 then more power to you. It means that you can’t take advantage of features that don’t exist in Windows 98. Or are you saying Windows should never add any new features? Should Windows 1.0 have been the last version of Windows?
This seems like a brittle way to implement WM_CTLCOLORSTATIC. What if you have a custom control that queries WM_CTLCOLORSTATIC and WM_CTLCOLORDLG while drawing? Is it true that the standard Windows controls will always use the brush immediately before sending any other CTLCOLOR messages? (presumably yes)
It seems strange to force the drawing code to remember that the brushes it gets may become invalidated and change colors at odd times.
Okay Raymond, and now read my post in the context of Adrian’s post.
What do you suggest should be done to fix it? Should Windows stop adding features so people won’t be tempted to use them?
I believe Adrian already did this.
Raymond, should you call DefWindowProc directly, or should you call it via CallWindowProc?
To position multiple child windows at one go.
To position multiple child windows at one go.
To position multiple child windows at one go.