Udostępnij za pośrednictwem


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

  • Anonymous
    April 18, 2006
    Tim Sneath has a great write-up on what it takes to give you app some Glass. It's surprisingly simple....

  • Anonymous
    April 18, 2006
    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!

  • Anonymous
    April 19, 2006
    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.

  • Anonymous
    April 19, 2006

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

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

  • Anonymous
    April 22, 2006
    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?

  • Anonymous
    April 24, 2006
    Tim Sneath, Windows Vista tech evangelist extraordinaire, has a good post up on how to add...

  • Anonymous
    April 25, 2006
    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)

  • Anonymous
    April 27, 2006
    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?

  • Anonymous
    April 27, 2006
    PingBack from http://microsoft.blognewschannel.com/index.php/archives/2006/04/27/vistas-aero-glass-inside-applications/

  • Anonymous
    April 27, 2006
    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?

  • Anonymous
    April 29, 2006
    The comment has been removed

  • Anonymous
    April 30, 2006
    The comment has been removed

  • Anonymous
    May 03, 2006
    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.

  • Anonymous
    May 03, 2006
    And what about adding glass in WPF application?

  • Anonymous
    May 03, 2006
    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. :)

  • Anonymous
    May 04, 2006
    Recently Tim shared some code for extending Windows Vista Aero "Glass" inside a Windows Forms window. ...

  • Anonymous
    May 04, 2006
    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...

  • Anonymous
    May 05, 2006
    PingBack from http://www.nexusblogs.com/blogs/blogs-blog-at-runboardcom/

  • Anonymous
    May 07, 2006
    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?

  • Anonymous
    May 07, 2006
    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.

  • Anonymous
    May 07, 2006

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

  • Anonymous
    May 24, 2006
    Ok, so one of the things I hope to achieve with this blog is to share all of the little gems that I come...

  • Anonymous
    May 27, 2006
    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?

  • Anonymous
    June 04, 2006
    The great thing about working at a company the size of Microsoft is that sometimes people get things...

  • Anonymous
    June 07, 2006
    Oguz: as you can see I've asked the same question, multiple times, but I can't seem to get an answer.

  • Anonymous
    June 09, 2006
    It's not C++, its C#, coreyw.

  • Anonymous
    June 11, 2006
    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?)

  • Anonymous
    June 24, 2006
    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

  • Anonymous
    July 11, 2006
    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.

  • Anonymous
    July 12, 2006
    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?

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

  • Anonymous
    July 21, 2006
    Where I create a base class to allow windows forms to be all glassy.

  • Anonymous
    July 30, 2006
    The solution to the problem actually lies in...

  • Anonymous
    August 05, 2006
    How, would I get this right in VB6?

  • Anonymous
    August 15, 2006
    PingBack from https://blogs.msdn.com:443/hiroyuk/archive/2006/07/14/665393.aspx

  • Anonymous
    September 05, 2006
    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?

  • Anonymous
    September 06, 2006
    Hi. First off, apologies for the long absence. This was due to some project commitments, however, that...

  • Anonymous
    September 12, 2006
    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.

  • Anonymous
    September 13, 2006
    stafadnymdalfoy@yahoo.co.tv

  • Anonymous
    September 13, 2006
    For the most part, the Vista Desktop Window Manager is an end-user feature.  However, because it...

  • Anonymous
    October 30, 2006
    The comment has been removed

  • Anonymous
    December 16, 2006
    so, can anyone give this code in vb .net? i use .net, not c# for my apps... it'd be much appreciated.

  • Anonymous
    December 18, 2006
    I downloaded the sample program and instead of glass it's just all black, I am running Vista (RC1).

  • Anonymous
    December 31, 2006
    Aero Glass in WPF

  • Anonymous
    March 18, 2007
    PingBack from http://www.se7ensins.com/forums/windows-vista-tutorials/49660-how-add-aero-glass-your-programs-using-c-programming.html#post350643

  • Anonymous
    March 20, 2007
    Recently Tim shared some code for extending Windows Vista Aero "Glass" inside a Windows Forms window

  • Anonymous
    March 25, 2007
    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

  • Anonymous
    September 25, 2007
    PingBack from http://aongaang.wordpress.com/2007/09/26/%e0%b8%97%e0%b8%b3-aero-glass-%e0%b8%81%e0%b8%b1%e0%b8%9a-net-application-winapp/

  • Anonymous
    January 25, 2008
    PingBack from http://dev.activebasic.com/egtra/?p=93

  • Anonymous
    February 03, 2008
    PingBack from http://www.wh-forum.de/coding-webdesign-server/9883-vista-glass-erweitern-visual-basic.html#post197583

  • Anonymous
    February 16, 2008
    PingBack from http://jakemchugh.com/blog/?p=126

  • Anonymous
    July 17, 2008
    PingBack from http://chiafong6799.wordpress.com/2006/04/20/glass-more-glass-please/

  • Anonymous
    January 18, 2009
    PingBack from http://www.keyongtech.com/613303-transparent-window