Programming Vista:The 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
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.
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.
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.
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.
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 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.
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.
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.
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.