Vista Glass with WPF
One of the cool new things in Vista is support for blurring the background of partially transparent windows. This is often refered to as the "Vista glass" effect. If your computer has a good enough graphics card, you can see the glass effect on the borders of non-maximized windows. This glass effect can also be used within the client area of the window. An example of this is the title bar in Internet Explorer 7. The Vista start menu goes even further and sets its entire background to be glassy.
In this article, you will find code samples of using the Vista glass effect with the Windows Presentation Foundation (WPF).
Glass effect in Internet Explorer 7
With a Window Frame
To acheive the effect in the image above, follow these instructions:
Set the window background to "Transparent":
<Window x:Class="WpfGlassWithFrame.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300" Background="Transparent" Loaded="Window_Loaded">
<Grid>
</Grid>
</Window>
And use the following code:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
[Flags]
private enum DwmBlurBehindFlags : uint
{
/// <summary>
/// Indicates a value for fEnable has been specified.
/// </summary>
DWM_BB_ENABLE = 0x00000001,
/// <summary>
/// Indicates a value for hRgnBlur has been specified.
/// </summary>
DWM_BB_BLURREGION = 0x00000002,
/// <summary>
/// Indicates a value for fTransitionOnMaximized has been specified.
/// </summary>
DWM_BB_TRANSITIONONMAXIMIZED = 0x00000004
}
[StructLayout(LayoutKind.Sequential)]
private struct DWM_BLURBEHIND
{
public DwmBlurBehindFlags dwFlags;
public bool fEnable;
public IntPtr hRgnBlur;
public bool fTransitionOnMaximized;
}
[DllImport("dwmapi.dll")]
private static extern IntPtr DwmEnableBlurBehindWindow(IntPtr hWnd, ref DWM_BLURBEHIND pBlurBehind);
private void Window_Loaded(object sender, RoutedEventArgs e)
{
WindowInteropHelper windowInteropHelper = new WindowInteropHelper(this);
IntPtr myHwnd = windowInteropHelper.Handle;
HwndSource mainWindowSrc = System.Windows.Interop.HwndSource.FromHwnd(myHwnd);
mainWindowSrc.CompositionTarget.BackgroundColor = Color.FromArgb(0, 0, 0, 0);
DWM_BLURBEHIND blurBehindParameters = new DWM_BLURBEHIND();
blurBehindParameters.dwFlags = DwmBlurBehindFlags.DWM_BB_ENABLE;
blurBehindParameters.fEnable = true;
blurBehindParameters.hRgnBlur = IntPtr.Zero;
DwmEnableBlurBehindWindow(myHwnd, ref blurBehindParameters);
}
}
You may also download the sample Visual Studio 2008 project.
With an Extended Window Frame
To acheive the effect in the image above, follow these instructions:
Set the window background to "Transparent":
<Window x:Class="WpfGlassWithExtendedWindowFrame.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300" Background="Transparent" Loaded="Window_Loaded">
<Grid>
</Grid>
</Window>
And use the following code:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
[StructLayout(LayoutKind.Sequential)]
private struct MARGINS
{
public int cxLeftWidth; // width of left border that retains its size
public int cxRightWidth; // width of right border that retains its size
public int cyTopHeight; // height of top border that retains its size
public int cyBottomHeight; // height of bottom border that retains its size
};
[DllImport("DwmApi.dll")]
private static extern int DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS pMarInset);
private void Window_Loaded(object sender, RoutedEventArgs e)
{
WindowInteropHelper windowInteropHelper = new WindowInteropHelper(this);
IntPtr myHwnd = windowInteropHelper.Handle;
HwndSource mainWindowSrc = System.Windows.Interop.HwndSource.FromHwnd(myHwnd);
mainWindowSrc.CompositionTarget.BackgroundColor = Color.FromArgb(0, 0, 0, 0);
MARGINS margins = new MARGINS()
{
cxLeftWidth = -1,
cxRightWidth = -1,
cyBottomHeight = -1,
cyTopHeight = -1
};
DwmExtendFrameIntoClientArea(myHwnd, ref margins);
}
}
The margin fields are set to -1 to indicate that the window frame should be extended throught the entire window. It is also possible to extend the window frame to only some of the client area of the window by specifying positive margin values. This is probably what Internet Explorer 7 does.
You may also download the sample Visual Studio 2008 project.
Without a Window Frame
To acheive the effect in the image above, follow these instructions:
On the window, set the following properties:
- WindowStyle = "None": This gets rid of the window frame.
- ResizeMode = "NoResize": This gets rid of the resizing behavior.
- AllowsTransparency = "True": This is necessary to enable transparency when WindowStyle is set to "None".
- Background = "#01FFFFFF": This causes the background to appear transparent so that the glass is visible. However, note that the alpha component of the background color is "01". The alpha component must not be 0 or the user is able to click through the window.
<Window x:Class="WpfGlassWithoutFrame.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300" Loaded="Window_Loaded"
Background="#01FFFFFF"
WindowStyle="None" ResizeMode="NoResize" AllowsTransparency="True">
<Grid>
</Grid>
</Window>
And use the following code:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
[Flags]
private enum DwmBlurBehindFlags : uint
{
/// <summary>
/// Indicates a value for fEnable has been specified.
/// </summary>
DWM_BB_ENABLE = 0x00000001,
/// <summary>
/// Indicates a value for hRgnBlur has been specified.
/// </summary>
DWM_BB_BLURREGION = 0x00000002,
/// <summary>
/// Indicates a value for fTransitionOnMaximized has been specified.
/// </summary>
DWM_BB_TRANSITIONONMAXIMIZED = 0x00000004
}
[StructLayout(LayoutKind.Sequential)]
private struct DWM_BLURBEHIND
{
public DwmBlurBehindFlags dwFlags;
public bool fEnable;
public IntPtr hRgnBlur;
public bool fTransitionOnMaximized;
}
[DllImport("dwmapi.dll")]
private static extern IntPtr DwmEnableBlurBehindWindow(IntPtr hWnd, ref DWM_BLURBEHIND pBlurBehind);
private void Window_Loaded(object sender, RoutedEventArgs e)
{
WindowInteropHelper windowInteropHelper = new WindowInteropHelper(this);
IntPtr myHwnd = windowInteropHelper.Handle;
HwndSource mainWindowSrc = System.Windows.Interop.HwndSource.FromHwnd(myHwnd);
mainWindowSrc.CompositionTarget.BackgroundColor = Color.FromArgb(0, 0, 0, 0);
DWM_BLURBEHIND blurBehindParameters = new DWM_BLURBEHIND();
blurBehindParameters.dwFlags = DwmBlurBehindFlags.DWM_BB_ENABLE;
blurBehindParameters.fEnable = true;
blurBehindParameters.hRgnBlur = IntPtr.Zero;
DwmEnableBlurBehindWindow(myHwnd, ref blurBehindParameters);
}
}
You may also download the sample Visual Studio 2008 project.