Aero Glass inside a WPF Window

Recently Tim shared some code for extending Windows Vista Aero "Glass" inside a Windows Forms window.  It sounds like he's eventually planning on showing this with WPF (among other things).  I also looked into this for my upcoming WPF book, and I couldn't wait to share the results of my little WPF glass experiment!  Sorry, Tim, if I'm stealing your thunder!

NOTE: This code will require WPF Beta 2 or later (and Windows Vista).  I'll share the whole project (including an updated Internet Hearts app) when Beta 2 is released.

I took the WPF UI I created for the Internet Hearts migration, slapped it in a System.Windows.Window, and "glassified" it.  Here is the result:

I didn't change a thing in the Hearts UI, and everything worked as expected: the 2D & 3D animations, the elements that already had partial opacity (like the card table), etc.

And when doing a "Flip 3D" (which I'm surprisingly finding more useful than the standard Alt+Tab), the result is pretty cool:

Of course, I'm now breaking all sorts of style, usability, and performance guidelines by my overzealous use of glass, but it's still an interesting exercise!

All it took was this function, which extends the glass frame into the client area of any WPF Window based on the passed-in margin:

public class GlassHelper
{
  public static bool ExtendGlassFrame(Window window, Thickness margin)
  {
    if (!DwmIsCompositionEnabled())
      return false;

    IntPtr hwnd = new WindowInteropHelper(window).Handle;
    if (hwnd == IntPtr.Zero)
      throw new InvalidOperationException("The Window must be shown before extending glass.");

    // Set the background to transparent from both the WPF and Win32 perspectives
    window.Background = Brushes.Transparent;
    HwndSource.FromHwnd(hwnd).CompositionTarget.BackgroundColor = Colors.Transparent;

    MARGINS margins = new MARGINS(margin);
    DwmExtendFrameIntoClientArea(hwnd, ref margins);
    return true;
  }

}

We need the HWND of the Window to pass to DwmExtendFrameIntoClientArea, and WindowInteropHelper enables us to get it.  The MARGINS structure controls how much to extend the glass on each of the four sides.  To get the "sheet of glass" effect, you can pass -1 for all four sides.

The trickiest thing is knowing to set not only Window's Background to Transparent, but also the BackgroundColor of the corresponding HwndSource's CompositionTarget (which is set to black by default).

The MARGINS structure passed to DwmExtendFrameIntoClientArea is similar in spirit to WPF's Thickness type, so I chose to expose Thickness from ExtendGlassFrame and defined MARGINS with a constructor that does the conversion:

struct MARGINS
{
  public MARGINS(Thickness t)
  {
    Left = (int)t.Left;
    Right = (int)t.Right;
    Top = (int)t.Top;
    Bottom = (int)t.Bottom;
  }
  public int Left;
  public int Right;
  public int Top;
  public int Bottom;
}

The two DWM APIs are defined as follows:

[DllImport("dwmapi.dll", PreserveSig=false)]
static extern void DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS margins);

[DllImport("dwmapi.dll", PreserveSig=false)]
static extern bool DwmIsCompositionEnabled();

Finally, the Window calls ExtendGlassFrame inside OnSourceInitialized:

protected override void OnSourceInitialized(EventArgs e)
{
  base.OnSourceInitialized(e);
  // This can't be done any earlier than the SourceInitialized event:
  GlassHelper.ExtendGlassFrame(this, new Thickness(-1));
}

Note that with Thickness I can pass a single value (-1) that will be used for all four MARGIN fields.

I'm going to add dwmapi.dll (and other Windows Vista DLLs) to pinvoke.net so folks can start sharing managed signatures for new APIs such as this.  Enjoy!

Published 04 May 06 07:30 by Adam Nathan
Filed under:

Comments

# Eli said on May 4, 2006 11:44 AM:
Someone really needs to add some glass support to Window Forms.
# Adam Nathan said on May 4, 2006 11:57 AM:
Eli, see http://blogs.msdn.com/tims/archive/2006/04/18/578637.aspx.  Or were you hoping for more built-in support?
# keeron said on May 4, 2006 12:28 PM:
Any idea if there are plans to ship the DWM library (or similar library for Aero) for XP? I see lot of new applications that are built for Vista, also being supported on XP.. and like old times, we'll see

if(VER < 6)
... no glass
if(Ver >= 6)
 ... glass...

# Adam Nathan said on May 4, 2006 12:56 PM:
keeron, you're right.  You'll have to do something like

if (System.Environment.OSVersion.Version.Major < 6 || !DwmIsCompositionEnabled())
  // No glass
else
  // glass

Fortunately, in the case of glass it's pretty easy to have reasonable fallback behavior.  And applications that only run on Windows Vista need to consider this anyway in case the user doesn't have glass enabled.
# Ricciolo said on May 4, 2006 3:24 PM:
# Erno de Weerd said on May 5, 2006 10:41 AM:
# CedarLogic said on May 7, 2006 6:55 PM:

I&amp;rsquo;m starting to see more applications leveraging Aero Glass on Vista.&amp;nbsp; They look quite cool.&amp;nbsp;...
# INauseous() said on May 7, 2006 6:55 PM:
# Kevin Daly said on May 9, 2006 3:54 PM:
I don't have anything intelligent to say, I just want to observe that that effect looks absolutely beautiful.
Nifty-as-you-know-what.
# sheldon said on May 10, 2006 4:32 PM:
I assume this requires Vista and can not be executed on XP running the WinFX installation.

Just checking.
# imothep said on May 15, 2006 2:45 PM:
Hi
I see you're right...i'd like to ask you, how can make glass effect in vb.net if im usin xp. If it's possible please somebody write me a little code to use it.
Thnx
# Tom's miniBlog said on May 25, 2006 5:48 AM:
Currently, I am struggling with WinFX and I must admit that I do not like the way how WPF (Windows Presentation...
# Pablo Fernicola said on June 5, 2006 1:36 AM:
The DWM functionality will not be available on XP.  It is Windows Vista only, requires the new driver model (WDDM).

-Pablo
# Kam VedBrat said on June 5, 2006 1:43 AM:
The great thing about working at a company the size of Microsoft is that sometimes people get things...
# Robert McLaws said on June 5, 2006 2:57 AM:
Adam, thanks for the !DwmIsCompositionEnabled function. That is most of the solution for the problem I was having in my WinForms app. Question, though: is there an event I can subscribe to that my WinForms app can handle incase Composition state changes? The problem I'm having is that I do my dev work in VirtualPC, and VPC turns DesktopComp off. So When I test my app, and DesktopComp goes off, it looks terrible. But since there's no event to handle... can't fix it. Any thoughts?

Thanks!
# Aero Glass inside a WPF Window » MSBLOG said on June 12, 2006 11:21 PM:
PingBack from http://www.msblog.org/?p=771
# .NET MVP KenLin's Blog said on June 19, 2006 10:24 PM:
Searching from google about WPF, I found a cool blogger. His name is Adam Nathan, He is good in Win32API...
# Computer Guru said on July 29, 2006 3:29 AM:
Hi,

Beta 2 has been released, don't want to beg, but: Can we have the code?

Thanks! :D
# jpelak said on August 16, 2006 10:23 PM:
Does this still work on June CTP + 5456?
# Adventures with WPF said on September 7, 2006 3:52 AM:
Hi. First off, apologies for the long absence. This was due to some project commitments, however, that...
# Greg Schechter's Blog said on September 14, 2006 4:37 AM:
For the most part, the Vista Desktop Window Manager is an end-user feature.&amp;nbsp; However, because it...
# Shell Blog said on September 25, 2006 5:00 AM:
One of the reasons we created this site was to give some insight into feature design decisions or why
# I Got Rhythm said on November 5, 2006 6:09 PM:

Style Snooper (or StyleSnooper?), originally posted by Lester, is a tool that can extract control styles

# » 0×1F4 - Transparency by Jordan Hofker said on January 16, 2007 9:53 PM:

PingBack from http://jordan.hofker.org/?p=116

# 匡匡 said on February 7, 2007 8:30 PM:

今天在网上看到一篇讲解在 WPF 窗口内部使用 Aero 效果的文章。文章地址 Aero Glass inside a WPF Window

# Adventures with WPF said on February 27, 2007 4:40 AM:

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

New Comments to this post are disabled
Page view tracker