Udostępnij za pośrednictwem


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!

Comments

  • Anonymous
    May 04, 2006
    Someone really needs to add some glass support to Window Forms.
  • Anonymous
    May 04, 2006
    Eli, see http://blogs.msdn.com/tims/archive/2006/04/18/578637.aspx.  Or were you hoping for more built-in support?
  • Anonymous
    May 04, 2006
    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...

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

    I&amp;rsquo;m starting to see more applications leveraging Aero Glass on Vista.&amp;nbsp; They look quite cool.&amp;nbsp;...
  • Anonymous
    May 09, 2006
    I don't have anything intelligent to say, I just want to observe that that effect looks absolutely beautiful.
    Nifty-as-you-know-what.
  • Anonymous
    May 10, 2006
    I assume this requires Vista and can not be executed on XP running the WinFX installation.

    Just checking.
  • Anonymous
    May 15, 2006
    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
  • Anonymous
    May 24, 2006
    Currently, I am struggling with WinFX and I must admit that I do not like the way how WPF (Windows Presentation...
  • Anonymous
    June 04, 2006
    The DWM functionality will not be available on XP.  It is Windows Vista only, requires the new driver model (WDDM).

    -Pablo
  • Anonymous
    June 04, 2006
    The great thing about working at a company the size of Microsoft is that sometimes people get things...
  • Anonymous
    June 04, 2006
    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!
  • Anonymous
    June 12, 2006
    PingBack from http://www.msblog.org/?p=771
  • Anonymous
    June 19, 2006
    Searching from google about WPF, I found a cool blogger. His name is Adam Nathan, He is good in Win32API...
  • Anonymous
    July 28, 2006
    Hi,

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

    Thanks! :D
  • Anonymous
    August 16, 2006
    Does this still work on June CTP + 5456?
  • Anonymous
    September 06, 2006
    Hi. First off, apologies for the long absence. This was due to some project commitments, however, that...
  • Anonymous
    September 13, 2006
    For the most part, the Vista Desktop Window Manager is an end-user feature.&amp;nbsp; However, because it...
  • Anonymous
    September 24, 2006
    One of the reasons we created this site was to give some insight into feature design decisions or why
  • Anonymous
    November 05, 2006
    Style Snooper (or StyleSnooper?), originally posted by Lester, is a tool that can extract control styles
  • Anonymous
    January 16, 2007
    PingBack from http://jordan.hofker.org/?p=116
  • Anonymous
    February 07, 2007
    今天在网上看到一篇讲解在 WPF 窗口内部使用 Aero 效果的文章。文章地址 Aero Glass inside a WPF Window
  • Anonymous
    February 26, 2007
    Hi. First off, apologies for the long absence. This was due to some project commitments, however, that