Search code examples
c++mfcgdi+gdi

Get an Image/Bitmap from a device context or graphics object in gdiplus (GDI+)


I'm looking for a way how this GDI code to get a bitmap from a Device Context...

void CMFCDlg::OnPaint()
{
    CDC dc(this);   // Device Context for painting
    CBitmap backgroundBmp;

    // Get Client Area
    CRect clientRect;
    GetClientRect(&clientRect);

    // Create memory DC
    CDC memDC;
    memDC.CreateCompatibleDC(&dc);

    // Create compatible bitmap
    backgroundBmp.CreateCompatibleBitmap(&memDC, clientRect.Width(), clientRect.Height());

    // Copy Blt Bits from DC to Bitmap
    CBitmap* pOldBmp = dc.SelectObject(&backgroundBmp);
    memDC.BitBlt(0, 0, clientRect.Width(), clientRect.Height(), &dc, 0, 0, SRCCOPY);
    dc.SelectObject(pOldBmp);

    // Release the memory DC
    memDC.DeleteDC();
}

...can be done in GDI+ to receive a GDI+ Image or Bitmap.

I'm looking for some way to do it close to this draft:

void CMFCDlg::OnPaint()
{
    CDC dc(this);   // Device Context for painting
    Bitmap backgroundBmp;

    // Get Client Area
    CRect clientRect;
    GetClientRect(&clientRect);

    // Get graphics object from device context
    Graphics gr(dc);

    // Somehow create a compatible GDI+ bitmap
    backgroundBmp = gr.??????
}

I've only seen code involving GDI Objects and resources which later get converted to GDI+ Objects. But none of them worked for me yet and I feel like there is an (easy) other way to do this with the much more comfortable GDI+ environment.


Solution

  • You can only draw GDI+ to device context. But you can use memory device context and then draw to dc or save to file:

    CClientDC dc(this);
    
    CDC memdc;
    memdc.CreateCompatibleDC(&dc);
    CBitmap bitmap;
    bitmap.CreateCompatibleBitmap(&dc, 100, 100);
    CBitmap *oldbitmap = (CBitmap*)memdc.SelectObject(&bitmap);
    
    Gdiplus::Graphics graphics_memdc(memdc);
    Gdiplus::Pen pen(Gdiplus::Color(255, 0, 128, 255), 5);
    Gdiplus::Rect rect(10, 10, 80, 80);
    graphics_memdc.DrawRectangle(&pen, rect);
    

    Now draw to dc

    dc.BitBlt(0, 0, 100, 100, &memdc, 0, 0, SRCCOPY);
    memdc.SelectObject(oldbitmap);
    

    or use CImage to save memdc to a file

    CImage cimage;
    cimage.Create(100, 100, 32);
    HDC imageHDC = cimage.GetDC();
    ::BitBlt(imageHDC, 0, 0, 100, 100, memdc.GetSafeHdc(), 0, 0, SRCCOPY);
    cimage.Save(L"c:\\test\\fileName.jpg", GUID_NULL);
    cimage.ReleaseDC();