Glass in C#, an alternative approach

Sun, July 30, 2006, 03:46 PM under Windows | Vista
My blog post on extending Windows Vista's glass into the client area of managed applications seems to have drawn a lot of attention (and some questions). If you haven't already, please read glass and C# (it assumes you are already familiar with Glass on Vista).

In that approach we looked at 5 steps. There is an alternative approach to extending glass with C# on Vista. The alternative approach has the same 1st and 2nd steps. The step that changes is the 3rd step: explicitly using a black brush to paint the extended area of the form in the form's paint event handler.

Rather than do that, do this:
3. Place a panel on the form's top edge, set the panel's BackColor to color X and then set the form's TransparencyKey to the same color X.

When you run the application, the area occupied by the panel will have the glass effect :-)

Note that just using the BackColor of a panel combined with TransparencyKey of form, results in transparency (also applicable to WinXP). The fact that we do that on Vista in an area that we extended with DwmExtendFrameIntoClientArea, is what gives it the glass effect.

This approach of using panels and transparency was first described (afaik) by Tim Sneath here. If you read the comments on Tim's blog post you'll find a heap of unanswered questions regarding a fundamental problem: At runtime, clicking anywhere on the glass area, actually brings to the front the application behind it. In other words, there is true transparency i.e. inability to click on the glass area while retaining focus in this application.

The solution to the problem actually lies in what color you pick. Above I state that you should pick color X but I have not said what X must be. In Tim's example, he picked Gainsboro. If you look at Gainsboro it has the following values: R=220, G=220, B=220. The problem of the unwanted true transparency stems from the fact that all values are equal. So if you just change for example the R to be 221, then the problem goes away :-) Another gotcha if you create your own color is setting the Alpha of the color to anything but 255 (doing that will not render as glass).

So, now we have two approaches for achieving the same goal (I still prefer the explicit black painting) and you can download a project with the transparencykey approach here. Before I finish off, it is worth pointing out that when a window is maximized, any glass area appears black, which is the reason that most windows rendered fully in glass, do not offer a maximize button (to the dismay of Goths I guess :-p).

While from a practical point of view it all works, some of you will have open questions such as "why black?" and "what makes one color result in true transparency while another doesn't". I'll try to answer those in a future blog entry (if no one else beats me to it).
UPDATE: This one does not work post-RC1. See here