Programming Vista: Using the Desktop Windows Manager (DWM) Interfaces

This is a recap of some of the information that I presented in my MSDN article Aero Glass:Create Special Effects With The Desktop Window Manager in the April 2007 edition of MSDN online here.

This tutorial assumes that you already have the following items set upon a machine with Windows Vista installed; For those of you not running Vista - sorry - the DWM is a Vista Only API due to the way that new driver system works with the desktop.

If you want to use the Glass interface the PC you’re running on will need to meet five requirements

    1. Visual Studio.NET is installed on your PC
    2. The latest platform SDK is installed on your PC.
    3. Running Vista Premium, Business or Ultimate editions.
    4. Running on a PC capable of running the “Aero” interface.
    5. Having the “Windows Aero” color scheme selected.

You enable the “Aero” scheme from the “Personalization” (previously called “Display”) and selecting “Windows Color and Appearance” and the selecting “Open classic appearance…” link and then selecting the Color Scheme. You’ll also have to have the “Enable Transparency” checkbox selected to be able to have the glass effect visible as well. Once you’ve got the Aero scheme running, you’ll be able to see the transparency effects for yourself.

It’s also possible to customize the window color and the opacity level. If you open up the “Personalize” options in the control panel (which is where the “Display” property has gone) you can select the basic window color and transparency of the Aero effect for your windows.  The Window Color and Appearance dialog is shown below. You can see the various settings that are user selectable – all of which will effect how the “glass” effect is rendered in your windows.

The Desktop Window Manager is where the new features of the Vista windows interface reside.  The Desktop Window Manager (DWM) is the new interface that manages how the various windows that are running and rendering are merged onto the Window’s desktop. The other parts are the Windows Presentation Foundation (WPF – aka Avalon)  a higher level layer that control the rendering to the desktop layer, and a new driver specification: the Windows Display Driver Model (WDDM) which handles the actual low-level rendering to the actual display. I’m only going to talk about using the DWM interfaces. WPF is available with any platform running .NET 3.0, and you should read the  MSDN article Introducing Windows Presentation Foundation  by Dave Chappell and many of the articles in Greg Schechter's Blog if you want to learn more about programming WPF.

Technical Overview of the DWM

The DWM interface is only be available on Vista (and later) systems (but not Vista Basic) and is housed in dwm.exe. Your application can call interfaces in dwmapi.dll (the public interface of DWM) which will then pass them along to dwm.exe. The interface declarations are found in dwmapi.h and you can get up-to-date API information online from windowssdk.msdn.microsoft.com. If you want to program Vista you’ll need Visual Studio 2005 and a copy of Vista. Vista comes with .NET 3.0 installed.

If DWM is running, it gets its input from WPF. In order to understand how DWM does what it does, it helps to understand what WPF does. Rendering at this level means rendering to a DirectX device, since Vista was designed to use graphics accelerators for every window, not just 3D DirectX applications. In order to do this WPF is the ultimate owner of the graphics processor and video memory. The render thread in WPF owns the DX device and is a separate thread, inaccessible to the user. Each process also usually has its own rendering/UI thread. The DWM gets a list of windows and manages their bitmaps in a tree structure which it then composites onto the final desktop.

The main window thread creates the scene, the scene is passed to the render thread and the render thread updates the desktop through its DirectX interface. The information passed is compacted to just deltas from the previous render, and large data, like images, are placed in shared memory. This can potentially allow the actual scene generation to be on one machine while the final rendering can be on another machine. 3D programmers who have used OpenGL will be familiar with this architecture. This architecture allows a server to manage a 3D scene and just send deltas to the client machines - so you could theoretically have a distributed rendering of a 3D scene and have it running with full hardware acceleration on any number of client machines. Unfortunately while the architecture supports this, this type of distributed rendering isn't supported.

Overview of the DWM Functions

The DWM controls how windows interact with the desktop composition engine. Being able to integrate your program into the DWM functionality requires that you gain an understanding of how the DWM works and how you can interact with it. Basically the DWM has four areas that it controls.

  1. Setting and querying basic desktop composition settings.
  2. Rendering the “glass” effect in a client window.
  3. Registering and Rendering “thumbnails”.
  4. Tuning the DWM rendering for interaction with multimedia programs and scheduling.

I’m going to cover the first three sections in this article. The last one is provided for DirectX and video playback applications because the DWM is running asynchronously which can lead to sampling artifacts if not tightly controlled.

Controlling the DWM Composition Settings

If you want to be able to use the desktop composition functionality in your program, you’re going to need to query and set various DWM parameters. For example, if some application switches into full screen then DWM turns off composition and renders in the desktop background color with no blending – your application should recognize this situation and turn off composition. These are the basic functions for integrating your program with the DWM.

Two other messages can also be sent by/for a DWM managed window:

Rendering Glass in a Window

Rendering the glass effect in your program is pretty simple, The DWM provides two functions to allow you to do that, a simple one that simply extends the non-client frame edge into your window, and a more complicated one that give you a lot more control over what and how the glass effect is rendered. It's the responsibility of the application to ensure that the areas being presented that will now have blurred glass behind them are rendered with the proper transparency values in the alpha channel. Unfortunately, very few GDI functions respect alpha (really the "alpha blit" function in GDI is the only one that reliably does). You may be forced to render your GDI content offscreen, use memory operations to clean up the alpha channel, and then alpha blit back.

You'll see a number of performance warning regarding blurring a window, but so far I haven't see any significant hits on any apps that I've written.

DWM Thumbnail functions:

Since all composited windows are rendered to an off-screen window by the DWM for later composition onto the desktop, it’s a simple matter to take those images and provide a live “thumbnail” representation of an application. Thumbnails can also be any size - smaller or larger than the original window's size. And these are real-live windows! If there's video playing in a window, the thumbnail will have the video playing. These are not snapshots, these are the actual, live windows rendering. The thumbnail API allows you get the DWM to render to your application as well as the desktop. You are just hooking in your HWND in the rendering list for some other HWNDs rendering. The DWM provides four functions to let you control how thumbnails get rendered.

  1. DwmQueryThumbnailSourceSize: Returns the source size of the DWM thumbnail.
  2. DwmRegisterThumbnail: Creates a DWM thumbnail relationship between the destination and source windows.
  3. DwmUnregisterThumbnail: Removes a DWM thumbnail relationship created by DwmRegisterThumbnail.
  4. DwmUpdateThumbnailProperties: Updates the properties for a given DWM thumbnail.

Thumbnails are implemented in pretty much the sam way as WPF's VisualBrush. Because thumbnails are links to other windows, it's possible to make relationships -- a thumbnail of another thumbnail, etc.or even having many thumbnails registered - which is exactly what Alt-Tab does in Vista Aero. Circular links of thumbnails are prevented.

DWM Compositing and Frame Timing functions.

The DWM has five functions to provide fine-tuning of how the DWM renders. These functions allow for finer grained control of exactly when the desktop is composited and presented.This is typically needed by media and video-playback applications since the DWM is running asynchronously. Used to prevent sampling artifacts.

  1. DwmEnableMMCSS: Tells the DWM to opt into Multimedia Class Schedule Service (MMCSS) scheduling while the calling process is alive. Typically used for video playback windows.
  2. DwmGetCompositionTimingInfo: Retrieves the current composition timing information.
  3. DwmModifyPreviousDxFrameDuration: Changes the number of refreshes the previous frame will be displayed.
  4. DwmSetDxFrameDuration: Sets the number of refreshes to display the presented frame.
  5. DwmSetPresentParameters: Sets the present parameters for frame composition. Allows an app to specify when one or more DirectX render target(s) are presented.