Click here to Skip to main content
11,933,180 members (63,395 online)
Rate this:
Please Sign up or sign in to vote.
See more: C++ GDI+ Direct2D
I'm converting a custom MFC control from GDI+ to Direct2D. The control sits on a dialog which has a bitmap background. I need to capture the portion of the dialog background which sits under the control so that I can render the background in the control's OnPaint() function. Is there a way to capture the dialog background to a bitmap in Direct2D?

In GDI+ this is pretty straight forward. You just create a dc compatible with the dialog dc. Create a compatible bitmap, load it into the dc and then BitBlt the dialog dc into the compatible dc. The bitmap can then be drawn using GDI+.

I've tried doing something similar in Direct2D but it's not working. I created a ID2D1DCRenderTarget object and then bound the object to the dialog dc. I then called ID2D1DCRenderTarget::CreateCompatibleRenderTarget() which creates a ID2D1BitmapRenderTarget object. I can then call GetBitmap() on the object but it doesn't seem to return a valid bitmap that I can render onto the custom control?
Posted 4-Oct-10 14:42pm

1 solution

Rate this: bad
Please Sign up or sign in to vote.

Solution 1

Ok, finally got this working. For anyone else who is interested, here are the steps required to capture the image from a device context and render it into a Direct2D render target. In my case I wanted to capture the image from an MFC CDialogEx dialog window that had a bitmap background.

The first steps require the use of GDI to copy a bitmap from the dialog device context to a memory device context. This can be done using CreateCompatibleDC(), CreateCompatibleBitmap() and BitBlt(). I stored the resulting bitmap in an MFC CBitmap object.

The trick now is to get the bitmap into a ID2D1Bitmap object so that we can render it to the render target. This is achieved using the Windows Imaging Component (WIC).

First, call IWICImagingFactory::CreateBitmapFromHBITMAP(), passing in the CBitmap we created earlier. This will create an IWICBitmap object. The IWICBitmap object now needs to be converted to a 32bppPBGRA pixel format. This is done using a IWICFormatConverter object. Call IWICFormatConverter::Initialize() specifying the IWICBitmap object created previously.

Finally, call ID2D1RenderTarget::CreateBitmapFromWicBitmap(), passing in the IWICFormatConverter object created above. This will create an ID2D1Bitmap object that can now be drawn in the render target.

A snippet of code is shown below:

CClientDC dcParent(GetParent());
CRect rectClient;
CRect rectWindow;
CDC dcBackground;
CBitmap *pOldBitmap = NULL;
CBitmap DialogBitmap;
CComPtr<IWICBitmap> pDialogBitmap = NULL;
DialogBitmap.CreateCompatibleBitmap(&dcParent, rectClient.Width(), rectClient.Height());
pOldBitmap = dcBackground.SelectObject(&DialogBitmap);
dcBackground.BitBlt(0, 0, rectClient.Width(), rectClient.Height(), &dcParent, rectWindow.left,, SRCCOPY);
// Note that the WICBitmapAlphaChannelOption is very important. If we don't set it to a value that is compatible
// with the render target where we intend to draw the bitmap then a black bitmap will be drawn.
hr = theApp.g_pWICFactory->CreateBitmapFromHBITMAP(DialogBitmap, NULL, WICBitmapIgnoreAlpha/*WICBitmapUsePremultipliedAlpha*/, &pDialogBitmap);
if (SUCCEEDED(hr))
    // Convert the dialog bitmap to a 32bppPBGRA pixel format. Before Direct2D can use an image, it must be converted
    // to the 32bppPBGRA pixel format. To convert the image format, use the CreateFormatConverter method to create
    // an IWICFormatConverter object. Once created, use the Initialize method to perform the conversion.
    CComPtr<IWICFormatConverter> pFormatConverter = NULL;
    hr = pWICFactory->CreateFormatConverter(&pFormatConverter);
    if (SUCCEEDED(hr))
        // dither, pIPalette, alphaThresholdPercent, and paletteTranslate are used to mitigate color loss when converting
        // to a reduced bit-depth format. We do not need to do this so we use the following parameters:
        // dither set to WICBitmapDitherTypeNone,
        // pIPalette set to NULL,
        // alphaThresholdPercent set to 0.0f,
        // and paletteTranslate set to WICBitmapPaletteTypeCustom
        hr = pFormatConverter->Initialize(pDialogBitmap,                    // Input bitmap to convert
                                          GUID_WICPixelFormat32bppPBGRA,    // Destination pixel format
                                          WICBitmapDitherTypeNone,          // Specified dither pattern
                                          NULL,                             // Specify a particular palette
                                          0.0f,                             // Alpha threshold
                                          WICBitmapPaletteTypeCustom);      // Palette translation type.
        if (SUCCEEDED(hr))
            hr = pRenderTarget->CreateBitmapFromWicBitmap(pFormatConverter, NULL, &m_pParentBitmap);
            m_bParentBackgroundCaptured = true;

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Top Experts
Last 24hrsThis month

Advertise | Privacy | Mobile
Web02 | 2.8.151126.1 | Last Updated 10 Jan 2012
Copyright © CodeProject, 1999-2015
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100