Direct2D and the Desktop Window Manager

Many moons ago, when Windows Vista was still in beta, I wrote an article showing readers how to program with the Desktop Window Manager (DWM). I also followed up with another article showing readers how to display controls on glass. Both articles focused on User32/GDI which at the time was still the way to go for native application developers.

With the introduction of Windows 7 comes a brand new graphics platform for the application developer and that of course is Direct2D. So far MSDN Magazine has published two introductory articles I wrote about Direct2D. If you haven’t already done so please read Introducing Direct2D and Drawing with Direct2D. I’ll wait.

The upcoming December issue of the magazine will feature the next installment which covers some more advanced topics related to interoperability, but for now I thought I’d update the DWM saga for Direct2D as it’s just so simple. Whereas GDI barely tolerated the DWM, Direct2D just loves it.

Let’s say you just want to render the entire client and non-client area as a seamless sheet of glass and then use Direct2D to draw on top. Start by instructing the DWM to extend the frame into the client area as follows:

MARGINS margins = { -1 };

Verify(DwmExtendFrameIntoClientArea(windowHandle,
                                    &margins));

Now all you need to do is instruct Direct2D to use the same pixel format used when alpha blending with GDI, namely pre-multiplied BGRA:

const D2D1_PIXEL_FORMAT format =
    D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM,
                      D2D1_ALPHA_MODE_PREMULTIPLIED);

The format is used when initializing the render target properties:

const D2D1_RENDER_TARGET_PROPERTIES targetProperties =
    D2D1::RenderTargetProperties(D2D1_RENDER_TARGET_TYPE_DEFAULT,
                                 format);

The render target properties are then provided to the Direct2D factory object to create the render target as usual:

Verify(m_d2dFactory->CreateHwndRenderTarget(targetProperties,
                                            windowProperties,
                                            &m_target));

And that’s all there is to it. You can now render portions of your window with glass simply by using a brush or bitmap’s alpha channel. You might for example clear the render target before drawing as follows:

m_target->Clear(D2D1::ColorF(0.0f, 0.0f, 0.0f, 0.0f));

Hope that helps.

No Comments