Click here to Skip to main content
11,641,416 members (60,876 online)
Rate this: bad
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 13: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;   
        HRESULT hr = E_FAIL;   
        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
0 Mika Wendelius 400
1 DamithSL 213
2 CPallini 159
3 OriginalGriff 145
4 Afzaal Ahmad Zeeshan 129
0 Mika Wendelius 460
1 OriginalGriff 215
2 DamithSL 213
3 CPallini 169
4 Afzaal Ahmad Zeeshan 129

Advertise | Privacy | Mobile
Web03 | 2.8.150731.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