Home > MFC, Windows API > Using PrintWindow to capture screen or to take snapshot of a window!

Using PrintWindow to capture screen or to take snapshot of a window!

PrintWindow is a cool function which helps us in printing a windows contents to a DC. Normal usage will be that we pass a printer DC, but here we pass a custom DC with a bitmap selected into this DC. Internally PrintWindow uses WM_PRINT and WM_PRINTCLIENT(This is my assumption).

Here is a simple function which uses PrintWindow to get screen shots of a given window and prints the resultant capture bitmap to a given window.

// Sample call CaptureWindow( FindWindow(...), &MyDlg )
void CaptureWindow( CWnd* WindowToCapture, CWnd* PaintToWindow )
{
    if( !WindowToCapture ||
        !PaintToWindow ||
        !IsWindow( WindowToCapture->m_hWnd ) ||
        !IsWindow( PaintToWindow->m_hWnd ))
        return;

    CDC* WindowToCaptureDC = WindowToCapture->GetWindowDC();
    CDC* PaintToWindowDC = PaintToWindow->GetDC();

    CDC CaptureDC;
    VERIFY( CaptureDC.CreateCompatibleDC( WindowToCaptureDC ));
    const int RestorePoint = CaptureDC.SaveDC();

    CRect CaptureWndRect;
    WindowToCapture->GetWindowRect( &CaptureWndRect );

    CBitmap CaptureBmp;
    VERIFY( CaptureBmp.CreateCompatibleBitmap( WindowToCaptureDC, CaptureWndRect.Width(), CaptureWndRect.Height() ));
    CaptureDC.SelectObject( &CaptureBmp );

    // Capture window now
    if( WindowToCapture->PrintWindow( &CaptureDC, 0 ))
    {
        CRect PaintToWindowRect;
        PaintToWindow->GetClientRect( &PaintToWindowRect );

        // To prevent unwanted stretching while drawing
        const int BltWidth = min( PaintToWindowRect.Width(), CaptureWndRect.Width() );
        const int BltHeight = min( PaintToWindowRect.Height(), CaptureWndRect.Height() );

        PaintToWindow->Invalidate();
        PaintToWindow->UpdateWindow();
        PaintToWindowDC->StretchBlt( PaintToWindowRect.left,
                                     PaintToWindowRect.top,
                                     BltWidth,
                                     BltHeight,
                                     &CaptureDC,
                                     0,
                                     0,
                                     CaptureWndRect.Width(),
                                     CaptureWndRect.Height(),
                                     SRCCOPY );
    }// End if

    CaptureDC.RestoreDC( RestorePoint );
    CaptureDC.DeleteDC();

    WindowToCapture->ReleaseDC( WindowToCaptureDC );
    PaintToWindow->ReleaseDC( PaintToWindowDC );
}

If you need to print just the client area of a window use PW_CLIENTONLY in nFlags parameter to this function! Note that if you are using PW_CLIENTONLY then change from GetWindowDC to GetDC.

A sample project for download (rename to zip). But there is a problem while capturing desktop window, whole desktop window painting goes haywire. I am working on it, will update this post with my fixes!

Advertisements
  1. Jithin
    August 9, 2008 at 8:28 am

    but how can i capture a TreeView window? when i used to pass the tree handle to PrintWindow(), it fails to take the screenprint..

  2. July 30, 2008 at 2:48 pm

    Since popup menus are also basically windows we can capture them, but problem is that they vanish too quickly. So we’ve got to hook its creation. Have a look at WH_CBT!

  3. Alex
    July 30, 2008 at 1:21 pm

    Hello,
    nice code.

    But how can I take a snapshot of a menu ?
    Any ideas ?

    Best regards,
    Alex

  4. June 23, 2008 at 2:24 pm

    I was wondering why! 🙂

  5. Jack
    June 23, 2008 at 2:22 pm

    problem solved. PrintWindow() was working fine. I was making errors in converting it into bitmap.

  6. June 23, 2008 at 1:39 pm

    Will have a look and get back to you later!

    Nibu

  7. Jack
    June 23, 2008 at 1:37 pm

    Hey,

    PrintWindow() does not take snapshot of complete window? I am trying to take snapshot at 1280X1024 resolution? any idea?

    Thanks.

  8. May 13, 2008 at 5:37 am

    PrintWindow function is used for this purpose, directly pass a printer dc to this function.

    Check out this link( http://msdn.microsoft.com/en-us/library/ms535511(VS.85).aspx ) for more information how to create a printer DC.

    To get a screenshot of any window just pass the handle of this window to this function along with a printer DC.

  9. Jasmine
    May 13, 2008 at 4:31 am

    Hi Nibu,
    i m developing a GUI using VC++ and i need to print the currently displaying screen whenever print command is given. at that perticular time there may be 3-4 windows open and one of them may be partially visible. i need to take a snap shot of the screen and print it. i got we solutions but in those it will display the screenshot from which againg we need to select print command to print it. but i require it to print directly at one go.

    pls help me out…

    Regards,
    Jasmine

  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: