问题
I have a few window controls drawn on a bitmap as well as on colored background on a dialog-box. Would there be some possible way to make the window controls' background transparent? Currently they show the default colored background of a dialog-box.
Example - I tried to paste a solid blue bitmap and the two button controls have the noticeable default colored-rectangle background.

回答1:
This is easily solved by providing Windows with a handle to whichever brush you want it to use to paint your button's background. You do this whenever you receive the WM_CTLCOLORBTN message in the button's parent window's message handler.
I mocked up a little demo application that compares two different buttons side-by-side. Both are standard Win32 BUTTON
controls, but the one on the left handles the WM_CTLCOLORBTN
message and specifies a brush with the same color as the window background. You can see the difference immediately—the light gray (or, more precisely, the default color for 3D controls, COLOR_3DFACE
) fringes around the button's rectangle are gone and the button looks much better against the custom background color:

The effect also works in Windows XP with visual themes enabled—here's a screenshot of the same app:

And the code that I used to create the above effect is almost ridiculously simple. Add this to your app's main window procedure (MainWndProc
), as described above. You don't need to touch your buttons.
HBRUSH hButtonBackColor = NULL;
LRESULT CALLBACK MainWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CTLCOLORBTN:
{
if (!hButtonBackColor)
{
// Create the brush, if it hasn't already been created.
// (You can use any type of brush here; this is just an example.)
hButtonBackColor = GetSysColorBrush(COLOR_3DDKSHADOW);
}
return (LRESULT)hButtonBackColor;
}
// ...
}
}
However, make sure that the brush you specify represents exactly the same color as your window's background color—a transparent brush may not work properly. Similarly, for a patterned brush (does anyone use those anymore?), the brush's origin will need to be set to match the background.
Always make sure that you release any brushes that you create by calling DeleteObject!! In C++, you would do this by making a CBrush
object (or equivalent) a member of your dialog class so that it would be automatically destroyed. In C, you'd need to handle the WM_NCDESTROY
message and delete the brush manually.
Also note that you do not need to specify the BS_OWNERDRAW style in order for this trick to work. The example above uses two standard button controls, created using only the following window style flags: WS_CHILD
, WS_VISIBLE
, and BS_PUSHBUTTON
.
Of course, if your design is any more complex than the above example (e.g., your buttons overlap multiple backgrounds), you'll probably have to go the owner-draw route, instead. I just think that's overkill for a task as simple as the one you appear to be describing.
回答2:
I don't know if you can make a truly transparent background, but my solution may help you anyway. I've always solved it by using the WM_CTLCOLORBTN message in the main window's procedure.
Let's assume that we have a switch
, in which we process the messages received by the main window.
case WM_CTLCOLORBTN:
return (LRESULT)hBgColor;
break;
where hBgColor
is an HBRUSH
, for example:
HBRUSH hBgColor=CreateSolidBrush(RGB(0, 0, 255));
As I said before, this doesn't really make the control's background transparent - it just sets it to the specified color.
EDIT: I'm sorry, I've done a mistake before. I've written LPARAM
instead of LRESULT
. Now it's correct.
来源:https://stackoverflow.com/questions/4483599/transparent-background-of-xp-themed-control