Windows Vista Aero Pt. 1 – Adding Glass to a Windows Forms Application


In a brief departure from my usual ramblings about Windows Presentation Foundation, I wanted to write a couple of technical posts about using new Windows Vista shell features from managed code. To start off, I thought I’d talk about how to add glass to an existing WinForms applications.


Firstly, what do I mean by adding glass? As most people know, Windows Vista includes a new Aero theme; one aspect of that theme is the translucent borders that are supplied by the Desktop Window Manager. There’s a lot of subtle sophistication in the way window frames are drawn – a drop shadow from the window, glow effects over the maximize / minimize / close buttons, a reflective texture on the window frame itself – so it’s far more than just painting with a 50% opacity gray brush.


On suitably equipped machines, every window gets a glass frame (even Command Prompt!). But some applications extend that glass frame into the client area of the window for aesthetic reasons; for example, Internet Explorer extends glass into the address bar, and Windows Media Player uses glass for the playback controls. Your application can also take advantage of the API behind this to extend glass into its own client area. This isn’t free – there’s quite a hefty tax involved in rendering glass, so it’s something to use sparingly rather than as the background for your whole window. Nevertheless, it’s a great way to make your application feel like an integral part of the operating system on which it runs.


In this first part, I’ll show you how to add glass to a Windows Forms application; in future entries, I’ll cover some other related areas such as drawing text onto glass, using glass in a WPF application, and creating blur effects.


The single API call that does most of the dirty-work is the following one:


[DllImport(“dwmapi.dll”)]
public static extern int DwmExtendFrameIntoClientArea(
   IntPtr hWnd,
   ref MARGINS pMarInset
);


This call takes two parameters – a window handle and a MARGINS struct that contains information on how much extra the DWM should extend the frame on the top, left, right and bottom sides of the screen. Here’s the declaration for MARGINS:


[StructLayout(LayoutKind.Sequential)]
public struct MARGINS
{
   public int cxLeftWidth;
  
public int cxRightWidth;
  
public int cyTopHeight;
  
public int cyBottomHeight;
}


The one big challenge with glass is getting alpha-blending to work correctly. Without using alpha-blending, then the content that you place on the glass will overwrite the glass itself and make it invisible. This is a problem in GDI, since it has no awareness of an alpha channel, but it’s a little easier with GDI+. In your Windows Forms application, you simply need to set the TransparencyKey property to a color that you won’t use elsewhere in the application (I use Gainsboro, for reasons that will become apparent later). Then you can create one or more panels that are docked to the margins of your form and set the background color for the panel to the transparency key. Now when you call DwmExtendFrameIntoClientArea, the glass will show within its margins wherever you’ve set something of the appropriate transparency key.


Here’s an example of using the above API call (from a Form_Load event)


MARGINS margins = new MARGINS();
margins.cxLeftWidth = 0;
margins.cxRightWidth = 0;
margins.cyTopHeight = 45;
margins.cyBottomHeight = 0;

IntPtr hWnd = this.Handle;
int result = DwmExtendFrameIntoClientArea(hWnd, ref margins);


So long as you’ve created the panel appropriately, you should now see glass in your application. You can now draw buttons, labels or other controls onto the surface and so long as you set their background color to be transparent, you’ll see them integrating well with glass. Here’s an example screenshot that puts it all together:



There’s just one caveat, which is that the text smoothing doesn’t work out quite right. Since it uses the panel background to determine the color it should smooth against, you’ll hit problems if you pick a garish color for the transparency key such as Fuchsia – you’ll see that the text renders with a horrid pink glow. That’s because we’ve cheated a little bit with the text rendering. So long as you set the transparency color to something that’s close to a typical glass color, this effect is barely noticeable (you can just see a little white fringing around the title text above, if you look really closely). That’s why we chose Gainsboro as our color earlier. Fortunately, there’s a better way to do it – if a little more convoluted. Win32 actually provides a useful API for this situation called DrawThemeTextEx that renders the text correctly on glass and also provides an appropriate back-glow that helps distinguish the text when it’s over a complex background. Next time I cover this topic, we’ll look at that API as well as discussing how you can detect whether the DWM is present and enabled or not (which is important if you want your application to run downlevel).


Download the sample application and source code (requires Windows Vista to execute).


Comments (54)

  1. Anonymous says:

    Tim Sneath has a great write-up on what it takes to give you app some Glass. It’s surprisingly simple….

  2. Anonymous says:

    Is is possible to host the command window (cmd) in a totally transparent window? Thus the text/scrollbar appears on glass? That would look soooooo cool!

  3. Anonymous says:

    Thanks Tim, that’s a very useful post. There’s been surprisingly little information available relating to the DWM… I’m very interested in finding out more. I’d like to know more about what’s possible. I’d also very much like to see some information about how to add glass to a WPF application.

  4. Anonymous says:

    Here’s how to do it.  (Requires Windows Vista and some willingness to fiddle with how your app…

  5. Garry Trinder says:

    Hi Tim, is this specific to any version. On my install of Vista 5308 the text is transparent and the background is white.

  6. Anonymous says:

    Will I be able to deploy glass effects via command prompt in Windows XP? If not, can someone please tell me how to get a legitimate copy of Vista without subscribing to MSDN, TechNet, etc?

  7. Anonymous says:

    Tim Sneath, Windows Vista tech evangelist extraordinaire, has a good post up on how to add…

  8. Anonymous says:

    Hi,

    I was awaiting for such article on WPF. Thanks for the information you have given. I’ve even posted my issue on "Glass effect for windows forms" on MSDN forums. Thanks to forums too.

    We have got a new requirement where in my client was to host Visio (Office 12) drawing control with in a WPF window.

    Could you please let me know how can I go further of resolving this issue.

    Thanks in advances..

    crish (nseresha@hotmail.com)

  9. Anonymous says:

    I have a problem with this approach. Setting the TransparencyKey for a form actually has two effects: it makes all areas of the form with that colour transparent, and it causes all mouse events in such transparent areas to be executed against the window that’s behind the transparent area.

    When using TransparencyKey in conjunction with glass, I don’t want the second part to happen. If I use the DWM’s default glass colour (black) I get glass without this effect, but then any other black items drawn over the glass area (such as control text) also become glass.

    Is there any way to prevent this?

  10. Anonymous says:

    Looks like my comment got eaten. Here it goes again.

    I have a problem adding glass to my app. Using TransparencyKey works fine to make the glass visible, but it also has another result: all clicks on the area that would’ve been transparent (and are now glass) are executed on the window below the glass. This is not what I want of course. Any way to prevent this?

    I tried using a black brush, which seems the default "glass colour" but if I do that all other black elements (such as text) on top of the glass also become glass.

    Any help?

  11. Tim Sneath says:

    Hi Sven, sorry – your comment didn’t actually get eaten, but it did get lost amongst all the stupid search engine optimization spam that I have to moderate each day. Apologies.

    The problem is that GDI has no notion of transparency or an alpha channel, so there’s some fancy footwork required to deliver this. You need to pick a single color (any color) out of the 16.7 million available to be your transparency key. A color like black would be a poor choice just because it crops up with such high frequency, but a less common color (such as #FCFDFE) would probably be adequate for most purposes. Hope that helps…

  12. Anonymous says:

    Tim, no problem, I realize the amount of spam you have to deal with every day is likely quite high.

    The problem with using TransparencyKey is that it will cause mouse actions (clicks etc.) to operate on the window below the glass (you can try it with your sample app, it happens there too) and it’s that which I don’t want. How can I extend glass into my client area, but still have mouse clicks on the glass parts register as clicks on my window, instead of the window below it?

    I know it’s possible, IE7 et al do it too. But how?

  13. Mike Dimmick says:

    Sven: I know how you’d do it in a C++ app; Windows sends a WM_NCHITTEST message to your application before sending mouse messages, to work out what sort of mouse message (if any) it should send to the application’s input queue. By judicious handling of this message, you can make any part of your app act like a title bar, sizing border, or even completely transparent.

    Presumably you could override your form’s WndProc to handle WM_NCHITTEST.

  14. breton says:

    And what about adding glass in WPF application?

  15. Anonymous says:

    I’ve been looking at WM_NCHITTEST but it isn’t the solution. Once TransparencyKey is set, the window doesn’t receive WM_NCHITTEST messages (or any other mouse messages) for those areas whose colour matches the TransparencyKey.

    I’ve been checking using reflector, and TransparencyKey is implemented using the SetLayeredWindowAttributes Win32 function. And indeed, in the Platform SDK it says "Hit testing of a layered window is based on the shape and transparency of the window. This means that the areas of the window that are color-keyed or whose alpha value is zero will let the mouse messages through."

    So apparently, there is a way to extend glass into the frame without using a layered window with a color-key, since IE7 and other Vista applications manage to do it. But how? Is there perhaps some window style I can set for WS_EX_LAYERED windows that will prevent them from letting the mouse messages through? I don’t mind if you give me the C++ solution, I’m familiar with C++ and Win32 and not afraid of PInvoke. 🙂

  16. Anonymous says:

    Recently Tim shared some code for extending Windows Vista Aero "Glass" inside a Windows Forms window. …

  17. Anonymous says:

    TimS does a great post on getting the Vista “glass” look and feel in a WinForms app…

     

    http://blogs.msdn.com/tims/archive/2006/04/18/578637.aspx

  18. Anonymous says:

    I just checked with Spy++, and the windows neither Windows Media Player 11 or IE7 use WS_EX_LAYERED, so they are not using a transparency key for their glass areas. So, how do they do it?

  19. Anonymous says:

    Any chance someone could convert this to VB .net?  My C++ is a little rusty, to say the least. The only part I dont get is the dll import. The other parts I can use in VB easily I think.

  20. Anonymous says:

    I’m starting to see more applications leveraging Aero Glass on Vista.  They look quite cool. …

  21. Anonymous says:

    Ok, so one of the things I hope to achieve with this blog is to share all of the little gems that I come…

  22. Anonymous says:

    Hi, thanks for the tutorial. But there is one problem. The glass area client area is clikkeble trough the form it’s annoying. How can you disable that?

  23. Anonymous says:

    The great thing about working at a company the size of Microsoft is that sometimes people get things…

  24. Anonymous says:

    Oguz: as you can see I’ve asked the same question, multiple times, but I can’t seem to get an answer.

  25. Anonymous says:

    It’s not C++, its C#, coreyw.

  26. Anonymous says:

    Hmm, apps built with this would probably crash on pre-Vista systems with a DLL not found error.  Would there be a way to only DLLImport if the DLL exists?  (And instead use an in-source function if it doesn’t?)

  27. Anonymous says:

    Sven Groot, the problem with this approach is that it is used for  the Windows Forms package that comes with .NET. It doesn’t have the power and extras that the WPF has (despite the fact that WPF was built upon .NET).  You need to download the WPF Beta 2 (I think it comes with the WinFX SDK Beta 2) and go to the following website:

    http://blogs.msdn.com/adam_nathan/archive/2006/05/04/589686.aspx

  28. Anonymous says:

    I might have found a solution to the mouse inputs being sent to what ever is under the glass.  Try setting the Trans. Key to some random color, one that will blend text well if possible.  Then when the program start, if on Vista and glass is on, set the form background to that color.

  29. Anonymous says:

    Okay. It looks great. But it doesn’t work great. You get pick through the area where "Tim’s Groovy Calender App" is displayed. Namely, once you click the area, you actually click something that is behide the Glassy Calender window, not the Glassy Calender window itself. Can we correct this?

  30. Anonymous says:

    Windows Vista の特徴に半透明のウィンドウ フレームがあります。これは、Aero テーマが有効なときに表示されます。よく見ると、この半透明のウィンドウ フレームの裏側の画像には、ぼかしがかかっています。…

  31. Anonymous says:

    Where I create a base class to allow windows forms to be all glassy.

  32. Anonymous says:

    The solution to the problem actually lies in…

  33. Anonymous says:

    How, would I get this right in VB6?

  34. Anonymous says:

    This stuff doesn’t work in RC1. Not even the sample application.

    Can someone please post a recent tutorial that explains how to do this in RC1?

  35. Anonymous says:

    Hi. First off, apologies for the long absence. This was due to some project commitments, however, that…

  36. Anonymous says:

    this example does not work in Vista RC1 as SeBsZ said.

    i’ve used another code in this site,

    http://www.codeproject.com/useritems/textonglass.asp

    it works, but controls like buttons, labels, textboxes

    look so bad, i can’t find a solution for it.

  37. Anonymous says:

    For the most part, the Vista Desktop Window Manager is an end-user feature.  However, because it…

  38. Anonymous says:

    Il est possible de gérer le mode GLASS de vista au sein de sa propre application à l’image de Media Player

  39. Anonymous says:

    so, can anyone give this code in vb .net? i use .net, not c# for my apps… it’d be much appreciated.

  40. Anonymous says:

    I downloaded the sample program and instead of glass it’s just all black, I am running Vista (RC1).

  41. Anonymous says:

    Recently Tim shared some code for extending Windows Vista Aero "Glass" inside a Windows Forms window

  42. Anonymous says:

    A search on Google will return quite a lot of more or less complicated and complete articles on how to implement Windows Vista’s Aero glass look in your own .NET applications. This posting will describe how to achieve this effect with as little code as