Introduction
There are a number of articles regarding the use of the Vista Aero APIs from within a managed Win32 Forms application. However having searched around, it seems several are outdated due to changes implemented between early Vista betas and Vista's final release.
This article is a brief introduction into the use of the new Vista APIs for extending the Aero Glass area into a managed Win32 application.
Background
So what is Aero? Aero is the new graphics UI for Vista. If you're lucky enough to own a copy of Vista and meet the hardware requirements, you can enable Aero through the Windows colour schemes dialog. This enables the Aero scheme on all Windows and dialogs (including Win32 applications), and provides translucent borders and blur effects known as Aero Glass.
As well as being aesthetically pleasing, Aero Glass can be used to enhance a user interface by controlling the focus of specific elements on screen. Remember according the Vista design guidelines the Glass effect should be used judiciously. It may be cool to do, but Glass is really intended for small regions without text or UI in order to make the interface appear more lightweight and clean.
Extending Glass
By default when Aero is enabled, all Windows have a translucent Glass frame and title bar. Using the Windows APIs it's possible to extend this Glass effect further into the client area. They can also be used to create Glass panels inside the client area, but unfortunately in managed code this is not as easy as it should be, and there are some major limitations.
To display Glass within a Window you must first use the DwmExtendFrameIntoClientArea
API to extend Glass into the client area. Once this is done, any area within this region that is painted black will appear as a Glass surface. If the area is not painted, any Glass regions not hidden by controls will just appear black at runtime (rather than Glass). In previous beta versions of Vista this step did not appear necessary, which is why a lot of the samples in circulation do not appear to work.
Due the fact that Windows uses the colour black to mask out the Glass regions, this has an undesired effect on any Windows Form controls within the Glass area, including any black text which will be lost.
To get around this, it's best to use the drawing APIs to manually create any text and graphical elements within the Glass area, which will then allow the use of a black brush on the Glass surface. See Pang Wu's article for more detailed tutorials on these techniques (link below).
The Code
To use the Vista APIs we use a number of PInvoke
methods defined as follows:
[StructLayout(LayoutKind.Sequential)]
public struct MARGINS
{
public int Left;
public int Right;
public int Top;
public int Bottom;
}
[DllImport("dwmapi.dll", PreserveSig = false)]
public static extern void DwmExtendFrameIntoClientArea
(IntPtr hwnd, ref MARGINS margins);
[DllImport("dwmapi.dll", PreserveSig = false)]
public static extern bool DwmIsCompositionEnabled();
We can now use these methods to ensure Aero effects are enabled, and then call DwmExtendFrameIntoClientArea
to extend the Glass effect into the client area as follows. This only needs to be done once, so we can use the Forms OnLoad
method to set up the desired Glass region.
private MARGINS margins;
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (DwmIsCompositionEnabled())
{
margins = new Win32.MARGINS();
margins.Top = 20;
margins.Left = 20;
DwmExtendFrameIntoClientArea(this.Handle, ref margins);
}
}
We now paint any areas we want to display as Glass with a black brush. This is best done by overriding the Form's OnPaintBackground
method. There are several ways of doing this, to keep it simple we will first clear the background with a black brush to enable Glass in our defined region, and then repaint the non-Glass client area with it's original background colour.
protected override void OnPaintBackground(PaintEventArgs e)
{
base.OnPaint(e);
if (DwmIsCompositionEnabled())
{
e.Graphics.Clear(Color.Black);
Rectangle clientArea = new Rectangle(
margins.Left,
margins.Top,
this.ClientRectangle.Width - margins.Left - margins.Right,
this.ClientRectangle.Height - margins.Top - margins.Bottom
);
Brush b = new SolidBrush(this.BackColor);
e.Graphics.FillRectangle(b, clientArea);
}
}
In Summary
That concludes the basics of extending Glass into your managed Win32 client area, however there's a lot more to Aero, and this article barely scrapes the surface. With further API calls it's possible to turn the Glass blur effects on/off, or even define blurred shapes within the Glass panels. Luckily there are some great articles about taking this further, which cover detailed tutorials on adding text and graphics to your Glass panels. See further reading below for links.
In the future I hope to add more to this article, and investigate possible solutions for handling the colour masking required by the Glass regions.
History
- Initial release: Feb 2007
Further Reading
Mike Carlisle - Technical Architect with over 20 years experience in a wide range of technologies.
@TheCodeKing