Date: | October 28, 2011 / year-entry #261 |
Tags: | code |
Orig Link: | https://blogs.msdn.microsoft.com/oldnewthing/20111028-00/?p=9243 |
Comments: | 27 |
Summary: | A customer reported that their application uses transparent static controls positioned over a bitmap image control, but even though they set the Transparent property on the static control, the static control isn't transparent. The customer was kind enough to provide clear steps to illustrate the problem: Open Visual Studio 2005 or 2008. From the menu,... |
A customer reported that their application uses transparent static controls positioned over a bitmap image control, but even though they set the Transparent property on the static control, the static control isn't transparent. The customer was kind enough to provide clear steps to illustrate the problem:
The Transparent property in Visual Studio corresponds to
the
The observed behavior, therefore, matches the documentation:
The control underneath (the bitmap control) paints first,
and then the static control paints on top of it.
And a static text control paints by filling with the background brush
and drawing the text on top of it.
You can customize this behavior by responding to the
HBRUSH CTestDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor) { HBRUSH hbr = __super::OnCtlColor(pDC, pWnd, nCtlColor); if (pWnd->GetExStyle() & WS_EX_TRANSPARENT) { pDC->SetBkMode(TRANSPARENT); hbr = GetStockBrush(HOLLOW_BRUSH); // even better would be to use a pattern brush, if the background is fixed } return hbr; }
The customer appreciated the explanation but was puzzled as to
why the Transparent is available if it doesn't work.
"We understand that we can use the
The Why is the Transparent property offered for static controls when it doesn't actually work? Shouldn't it be disabled for static controls?
The reason why it is offered is that it is a general window style
that can be set on any control.
Visual Studio doesn't know which controls can render transparently
and which ones don't,
or what extra steps are necessary to get
the ones who can render transparently to actually do so.
It just exposes the In retrospect, it was a poor chose of name for the style. And the incorrect online help doesn't make things any better.
Bonus chatter:
Note that the |
Comments (27)
Comments are closed. |
I think there's no problem at all, because the blog software ate your image.
@JamesJohnston:
Huh? There's no image at all, just an amazingly cool "HTML-art image" of a dialog.
The "image" is creative use of CSS. It shows up fine for me, Chrome 14.
Didn't work the first time when I read the article on FF7, but Raymond seems to have fixed it stealthily ;-)
So that's why I never could get WS_EX_TRANSPARENT to work. I kept on trying to use it on top level windows and it only works if the overlapping windows are owned by the same thread.
Doesn't show properly in Google Reader (the label appears below the white square)
Oh my! That "x" in the corner seems to work as a submit button!
OK, now that I squint, I see there is a white square against a very very very light gray (almost white) background – or is it a very light brown? I don't know. I'm not sure why he picked a white square instead of, say, a bright red one.
The background all looked the same to me at first and so I assumed there should have been an image there – since the example he gave was a customer placing a label over the image.
Some of us have to work with crappy monitors that don't have good contrast… Or we have bad eyesight…
Doesn't matter how many times you report docs and source code samples for being bad and/or incorrect.
Like the sample not following the docs or vice verse.
Microsoft doesn't seem to care, they do not even bother to respond nor do they correct the mistakes.
It doesn't surprise me windows programs have so many bugs in them since they are programmed based on what they read in the docs. Docs buggy == programs buggy.
On that note, on slightly different topic, yet similar:
The Hilo (code.msdn.microsoft.com/Hilo) devs have not responded to my question so perhaps you Mr Raymond can answer this question:
HiloC++Commonsourcewindowfactoryimpl.cpp:
"wcex.hCursor = nullptr; // If the class cursor is not null, the system restores the class cursor each time the mouse is moved."
Isn't this inefficient behavior ?
If setting the cursor in registerclass is bad then where should you do it ?
Or can you not prevent this behavior / issue ?
When i created a basic window sample and setting hCursor to nullptr i get the donut cursor animation until i move the cursor out of the example window or moving the cursor to resize the example window which change the cursor to resize then changes it back to the normal expected arrow cursor.
Yes, i have checked RegisterClass/Ex and WNDCLASS/EX documentation. They mentioned something about it before but the new w8 design docs, have removed that hint. So i'm yet again in the dark about how to do it right.
Thank you for taking the time to read and answer.
@JamesWebb:
// If the class cursor is not null, the system restores the class cursor each time the mouse is moved.
Take time to go to Windows SDK documentation and read "About cursors (Windows)" topic.
"To override the class cursor, process WM_SETCURSOR message".
A window gets WM_SETCURSOR every time the cursor is moved. If you just pass it to DefWndProc, it will set the cursor to the registered class cursor. If you handle the message without passing it to DefWndProc, you can leave the cursor unchanged, or set it to your own custom one.
@JamesWebb: This is not Raymond's Suggestion Box. The Suggestion Box for future topics is currently closed due to the large backlog. You may get some answers here, or you may not. :-)
Even if I knew whom to contact at MS to ask such a question (I don't) I'd never think of doing it because I'd just use google (or bing if you like) and find n explanations to this issue.. just wondering if the support people are annoyed at such requests or glad that it's not a harder problem (eg a stack dump with no further context given)..
@JamesJohnston: The colors depend on your Windows system colors. The "white" is actually the "window" color while the "light grey" is actually the "3D face" color.
@JamesJohnston: I've noticed something odd about certain screens. The color (especially yellow) disappears at certain angles. If you adjust your viewing angle, you might notice a color suddenly appear.
@Puckdropper, CRTs don't usually do that, although most of us don't use them any more, of course.
This is yet another proof of ms releasing a half baked technology which requires a lot of additional coding to get working. EVERYTHING ms release is like this. Most often it's easier to code all things from scratch yourself instead.
Because when you add features like resizing of windows, and want non-corrupt drawing of graphics (in xp, vista & w7), things like gdi's "transparent" drawing apis is not that easy to make sense of any longer.
And don't be ridiculous, ofcourse visual studio can complain about setting the transparent bit on static window class. It's not like the static class will change it's behavior in the next windows hotfix. If the static class changes that much, ms will release a new sp/version of vs for sure because then it's not windows any more.
@640k Yes sadly there are no higher frameworks by MS that make using these things much simpler and easier. Oh wait, if programming with .NET (insert whatever you want here) you don't have to worry about WS_EX_TRANSPARENT and still get transparent windows?
Lowlevel stuff is by definition more complex, easier to get wrong and you won't get every small detail on first glance. The problems are complex, backwards compatibility has to be maintained, etc.
That's why there are many great highlevel frameworks that abstract all these details away from you.
In hindsight, WS_EX_TRANSPARENT really was a terrible name. As soon as we get that time machine running…
@alegr1
Thank you for helping.
@DWalker
I knew that even if i'd not known that it wouldn't have help my questions.
I've pretty much lost hope for msdn forums and mail-lists so Raymond was a shot in the dark for help. Raymond continues to provide very useful and informative knowledge of how and why windows works the way it does and how to communicate with it correctly.
We really do need more Raymond like blogs.
Tell your customer to switch from using Visual Studio to Delphi, that's the RAD IDE that works. Delphi stopped having any visual crappy issues since 90's, while VS still got'em high.
@JamesWebb: When all else fails, read the Wine sources. They're the result of porting a library definition to a large sample of running programs so they're probably right.
Please have the MSDN documentation updated so developers don't have to search for this (excellent) explanation somewhere else and everyone can understand the behaviour immediately.
@JamesWebb: There's an art in asking questions properly. By "properly", I mean, in a manner designed to maximize your chances of actually getting an answer.
Your Hilo forum question started: "Can the devs explain in detail why windows behaves like this?" If I were a dev, reading that forum, here's what I would have thought: "NO". That page is clearly a simple Q&A page. It's not the place for long and detailed explanations. So I wouldn't have read any further!
Here's what might have worked better: "I don't understand the cursor management in the example code. Can someone suggest some relevant reading on Windows cursor management?"
HTH
The way to use WM_CTLCOLOR as shown here will never work, if the static cntrol needs an update. It nly works if the background control and static control are just displayed once and are not changed.
Using a hollow background brush causes WM_ERASEBKGND to erase and clear nothing. And even if WS_EX_TRANSPARENT is set, the background of the static control is not repainted if SetDlgItemText/SetWindowText is executed for the static control! So the result are artifacts of the previous contents…
From my understanding a repaint of the static control with WS_EX_TRANSPARENT has to repaint underlying sibling control too, but this isn't the case!
Just my 2 cents!
Unfortunately, the real issue is that you cannot really do proper transparency with child hwnds — the only way to get it right with child hwnds is to have them all talking to each other so that they can fill their background with whoever is behind them. Even then, I am not sure if you can fully remove the flicker problem.
I assume this is the main reason why technologies like WPF simply don't use HWNDs for child objects — the only way to draw things right is for the parent window to draw everything.
Oh boy! Since I moved into WPF-land, I truly appreciate how awful Windows GDI/User APIs are. I know why they are where they are, and I know that WPF/XAML/GC have their own problems. But they are a *huge* improvement over the old-style code.
That said, the information in this post was helpful, so keep these tricks pumping out, sooner or later I will need one of them (as I already have plenty of times).
@CherryDT, Raymond: I have no special/unusual system configuration. It is a Windows 7 box with Aero Glass turned on, with all default settings. I'm not the type to change all my system colors. The blog is viewed under Google Chrome 15.
I think my point is still valid. Use explicit colors that you know will have an easily-seen contrast, rather than using the client computer's default colors which apparently don't have good contrast on some versions of Windows.