Like the cake, WS_EX_TRANSPARENT is a lie, or at least not the entire truth


There is an extended window style known as WS_EX_TRANSPARENT. Explaining what this style does is kind of difficult, but it's been on the list of future topics since 2003. Better late than never, I guess.

First of all, there are two unrelated senses of transparent in play. One is visual transparency: Pixels beneath the window can show through. The other is hit-test transparency: Do clicks on this window go to the window, or do they pass through to the window beneath?

And each of those senses of transparent is itself complicated.

Let's look a hit-test transparency first. We saw some time ago that It's Complicated. Different hit-testing functions use different methods of determining whether a click should be given to a window or pass through it. And the WS_EX_TRANSPARENT extended window style plays into some of those rules. I'll let you read the linked article to learn the details.

Okay, now to visual transparency. The WS_EX_TRANSPARENT extended window style alters the painting algorithm as follows: If a WS_EX_TRANSPARENT window needs to be painted, and it has any non-WS_EX_TRANSPARENT windows siblings (which belong to the same process) which also need to be painted, then the window manager will paint the non-WS_EX_TRANSPARENT windows first.

That "lets the other windows paint first" behavior is what gave the style its name, because if you let the other windows paint first, and then you paint on top of it, then the parts you don't actually paint will appear to be transparent because the other windows' pixels will show through.

Calling this painting style transparent is kind of overselling the feature. It's really a very specific behavior which makes transparent rendering sort of possible; it's not a just turn this on and you get transparent rendering feature.

It's like taking a lump of coal and labeling it diamond. Or like those advertisements which say things like "Can create up to five million cups of coffee per day!"

In order to turn the flour into a cake, the window with the WS_EX_TRANSPARENT window style needs to know not to draw opaquely. Because if it draws opaquely, then all the work the window manager did to get the other window to draw first (so you can draw on top of it) is for naught.

And sometimes the WS_EX_TRANSPARENT window style doesn't even work. For example, observe that if the windows are not siblings of each other, then the style has no effect. If the windows belong to different processes, then the style has no effect. If both windows are not invalid simultaneously, then the style has no effect. (I don't know how you could get into that last state, but maybe you're more creative than I am.)

Go ahead and use the WS_EX_TRANSPARENT window style if that's what you want. Just understand that it doesn't get you what the name might promise. (Depending on your situation, a layered window may work better.)

Comments (4)
  1. Joshua says:

    [If the windows belong to different processes, then the style has no effect.]

    Which is why it didn't work the one time I tried it on a top level window.

    [If both windows are not invalid simultaneously, then the style has no effect.]

    InvalidateRect() and ValidateRect() games.

  2. Portal reference…

    I never thought I'd see the day.

  3. Nawak says:

    @Crescens2k

    What about the Rubens Tube link in this post? blogs.msdn.com/…/9942466.aspx

    Not the same as a direct reference but close!

  4. Mark says:

    If I remember correctly, this was used for things like the text labels, which are as transparent as anything got back then.  The wording in the SDK ("is to be transparent") is confusing until you realise it's an assertion from the developer, not a request ("should be transparent").  It's like the author had consumer-tinted spectacles on, something that comes and goes in the Win32 documentation.

Comments are closed.