Screen Capture to the Clipboard

Back To Tips Page

One of the common questions that I find on the microsoft.public forums is "How do I get a bitmap of a window on the screen?" Well, here's a little subroutine I used extensively in writing Win32 Programming, because I realized that for the number of illustrations I wanted for the book, there was no hope of doing screen captures and then hand-editing just the control I wanted to show. So all my Explorers have a little button somewhere that performs a screen capture of the example window and drops it into the clipboard. I could then paste it into the document, or paste it into an editor and save it as a TIFF or JPEG as well.

To capture a window including the cursor, a more complex approach is required. This is described in an accompanying essay.

Note that I use a base CDC object and use Attach and Detach, instead of using the classes CClientDC and CWindowDC.  I did this because each of these classes creates a specific kind of DC, but there was no one class that could create a DC that was either a client DC or a Window DC.  Rather than introduce convoluted code to handle these cases, I just bound the HDC to a generic CDC.


void toClipboard(CWnd * wnd, BOOL FullWnd);


#include "stdafx.h"
#include "toclip.h" 
*                                 toClipboard
* Inputs:
*       CWnd * wnd: Window whose contents are to be sent 
*                   to the clipboard
*       BOOL FullWnd: TRUE for entire window, 
*                     FALSE for client area
* Result: void
* Effect: 
*       Copies the contents of the client area or the window
*       to the clipboard in CF_BITMAP format.
void toClipboard(CWnd * wnd, BOOL FullWnd)
     CDC dc;
        { /* full window */
         HDC hdc = ::GetWindowDC(wnd->m_hWnd);
        } /* full window */
        { /* client area only */
         HDC hdc = ::GetDC(wnd->m_hWnd);
        } /* client area only */
     CDC memDC;
     CBitmap bm;
     CRect r;
     CString s;
     CSize sz(r.Width(), r.Height());
     CBitmap * oldbm = memDC.SelectObject(&bm);
     memDC.BitBlt(0, 0,,, &dc, 0, 0, SRCCOPY);
     ::SetClipboardData(CF_BITMAP, bm.m_hObject);
     bm.Detach();  // make sure bitmap not deleted with CBitmap object
                   // read my essay on this technique
     ::ReleaseDC(wnd->m_hWnd, dc.Detach()); // 


Special thanks to Lim Bio Liong for pointing out that the CDC destructor does not call ReleaseDC. This bug was the result of converting some pure C code to MFC without my being careful enough.

Also, thanks to Charles Tam for pointing out a typo in the previous bug fix, a missing parameter.


Note that as of 7-Mar-02, there is an additional line (marked "New", above), which fixes a bug.


The line added 7-Mar-02 was incorrect, and required a first parameter to ::ReleaseDC
  Added an explanation of why I did not use CWindowDC or CClientDC

[Dividing Line Image]

The views expressed in these essays are those of the author, and in no way represent, nor are they endorsed by, Microsoft.

Send mail to with questions or comments about this web site.
Copyright 1999-2007 FlounderCraft, Ltd.,  All Rights Reserved.
Last modified: May 14, 2011