Search code examples
c++winapigdi

C++ Take a Screenshot


I'm new to C++ and have to take a screenshot. I think I have set up everything besides the print method itself and that's where I'm struggling.

I found a post on so which describes how to take a screenshot, but it somehow doesn't work for me. (How to capture part of the screen and save it to a BMP?)

My Method looks like this:

STDOVERRIDEMETHODIMP VImplPrintable::Print(HDC hdc, CRect* pCr)
{  
  HDC hdcSource = GetDC(NULL);
  HDC hdcMemory = CreateCompatibleDC(hdcSource);   

  int capX = GetDeviceCaps(hdcSource, HORZRES);
  int capY = GetDeviceCaps(hdcSource, VERTRES);

  HBITMAP hBitmap = CreateCompatibleBitmap(hdcSource, pCr->Width(), pCr->Height());
  HBITMAP hBitmapOld = (HBITMAP)SelectObject(hdcMemory, hBitmap);

  BitBlt(hdcMemory, 0, 0, pCr->Width(), pCr->Height(), hdcSource, pCr->top, pCr->left, SRCCOPY);

  DeleteDC(hdcSource);
  DeleteDC(hdcMemory);

  return S_OK;
}

Problem is the screenshot seems to be an empty bitmap. I don't really know if I it makes sense to create a new HDC when I'm already getting one as a parameter. Any help is appreciated.


Solution

  • I cannot test because I do not know what is the framework that calls that method, but as you receive the HDC you want to write to, you simply should not use a memory DC and directly BitBlt there. But you should also test the return value of WinAPI calls to return error conditions to the caller:

    STDOVERRIDEMETHODIMP VImplPrintable::Print(HDC hdc, CRect* pCr)
    {  
      HDC hdcSource = GetDC(NULL);
      if (NULL == hdcSource) return E_FAIL;
    
      HRESUL cr = S_OK;
    
      if (!BitBlt(hdc, 0, 0, pCr->Width(), pCr->Height(), hdcSource, pCr->top, pCr->left, 
          SRCCOPY)) cr = E_FAIL;
    
      DeleteDC(hdcSource);
    
      return cr;
    }