In an older article published at Codeguru, I showed how easy is to make screen capture using CImage ATL/MFC class. Here is the sample code from that article:
BOOL CScreenImage::CaptureRect(const CRect& rect) { // detach and destroy the old bitmap if any attached CImage::Destroy(); // create a screen and a memory device context HDC hDCScreen = ::CreateDC(_T("DISPLAY"), NULL, NULL, NULL); HDC hDCMem = ::CreateCompatibleDC(hDCScreen); // create a compatible bitmap and select it in the memory DC HBITMAP hBitmap = ::CreateCompatibleBitmap(hDCScreen, rect.Width(), rect.Height()); HBITMAP hBmpOld = (HBITMAP)::SelectObject(hDCMem, hBitmap); // bit-blit from screen to memory device context // note: CAPTUREBLT flag is required to capture layered windows DWORD dwRop = SRCCOPY | CAPTUREBLT; BOOL bRet = ::BitBlt(hDCMem, 0, 0, rect.Width(), rect.Height(), hDCScreen, rect.left, rect.top, dwRop); // attach bitmap handle to this object Attach(hBitmap); // restore the memory DC and perform cleanup ::SelectObject(hDCMem, hBmpOld); ::DeleteDC(hDCMem); ::DeleteDC(hDCScreen); return bRet; }
Like a walking in the park. 🙂 However, it can be made even easier, with fewer lines of code.
BOOL CCaptureImage::CaptureRect(const CRect& rcCapture) { // destroy the currently contained bitmap to create a new one Destroy(); // create bitmap and attach it to this object Create(rcCapture.Width(), rcCapture.Height(), 32, 0); // create virtual screen DC CDC dcScreen; dcScreen.CreateDC(_T("DISPLAY"), NULL, NULL, NULL); // copy the contents from the virtual screen DC BOOL bRet = ::BitBlt(GetDC(), 0, 0, rcCapture.Width(), rcCapture.Height(), dcScreen.m_hDC, rcCapture.left, rcCapture.top, SRCCOPY | CAPTUREBLT); // do cleanup and return dcScreen.DeleteDC(); ReleaseDC(); return bRet; }
Now, let’s add two more methods, one for capturing a given display monitor and one for capture a window.
BOOL CCaptureImage::CaptureDisplayMonitor(const MONITORINFO& monitorInfo) { return CaptureRect(CRect(monitorInfo.rcMonitor)); } BOOL CCaptureImage::CaptureWindow(CWnd* pWnd) { ASSERT_VALID(pWnd); CRect rcWindow; pWnd->GetWindowRect(rcWindow); return CaptureRect(rcWindow); }
Demo aplication
Download:
Screen Capture Demo.zip (1831 downloads)
The demo application makes per-monitor capture.

Resources and related articles
- MSDN: CImage Class
- Codeguru: Easy Screen Capture Using MFC/ATL
mess up in high DPI application,
can you fix it?
Thank you for pointing the DPI problem!
This is how can be fixed:
– open “Project Property Pages” dialog;
– go to Manifest Tool / Input and Output / DPI Awareness;
– choose “Per Monitor High DPI Aware”.