How to get screenshot of a window as bitmap object in C++?

36,121

Solution 1

you should call the PrintWindow API:

void CScreenShotDlg::OnPaint()
{
    // device context for painting
    CPaintDC dc(this);

    // Get the window handle of calculator application.
    HWND hWnd = ::FindWindow( 0, _T( "Calculator" ));

    // Take screenshot.
    PrintWindow( hWnd,
                 dc.GetSafeHdc(),
                 0 );
}

see this question: getting window screenshot windows API

if you are not using MFC, here the pure PrintWindow signature:

BOOL PrintWindow(
    HWND hwnd,
    HDC hdcBlt,
    UINT nFlags
);

see MSDN for more details: http://msdn.microsoft.com/en-us/library/dd162869(v=vs.85).aspx

about how to save it as bitmap asMatteo said depends on the actual framework you are using...

EDIT:

here full example in raw C++

#define _WIN32_WINNT    0x0501        //xp
#include <windows.h>

int main()
{ 
    RECT rc;
    HWND hwnd = FindWindow(TEXT("Notepad"), NULL);    //the window can't be min
    if (hwnd == NULL)
    {
        cout << "it can't find any 'note' window" << endl;
        return 0;
    }
    GetClientRect(hwnd, &rc);

    //create
    HDC hdcScreen = GetDC(NULL);
    HDC hdc = CreateCompatibleDC(hdcScreen);
    HBITMAP hbmp = CreateCompatibleBitmap(hdcScreen, 
        rc.right - rc.left, rc.bottom - rc.top);
    SelectObject(hdc, hbmp);

    //Print to memory hdc
    PrintWindow(hwnd, hdc, PW_CLIENTONLY);

    //copy to clipboard
    OpenClipboard(NULL);
    EmptyClipboard();
    SetClipboardData(CF_BITMAP, hbmp);
    CloseClipboard();

    //release
    DeleteDC(hdc);
    DeleteObject(hbmp);
    ReleaseDC(NULL, hdcScreen);

    cout << "success copy to clipboard, please paste it to the 'mspaint'" << endl;

    return 0;
}

Solution 2

If anybody is interested in getting PrintWindow picture of minimized window, here you can get the idea, how to get the thing done: http://www.codeproject.com/Articles/20651/Capturing-Minimized-Window-A-Kid-s-Trick

Happy coding;)

Solution 3

Looks like PrintWindow is working with frontbuffer. I tried to take an IE screenshot. Open new a link, and try to get the picture. It will show the picture from the previous link.

Share:
36,121
jondinham
Author by

jondinham

A diligent software engineer, quite a quiet one

Updated on September 02, 2020

Comments

  • jondinham
    jondinham over 3 years

    How to get screenshot of a window as bitmap object in C++? Supposed that I already have the window handle. And I want to know also whether it's possible to get the screenshot of a window when it's in minimized state?

    C++ here means VC++ with all the libraries associated with Windows XP+ (win32).

  • jondinham
    jondinham over 12 years
    @Davide: tks, but just can't find the description for the function PrintWindow in MSDN library (msdn.microsoft.com)
  • jondinham
    jondinham over 12 years
    @Davide: found the description for PrintWindow, but how to add MFC library to vc++ project?
  • jondinham
    jondinham over 12 years
    @Davide: ok, like your answer, however, is it (your method) able to take screenshot of minimized window? tks in advance
  • Matteo Italia
    Matteo Italia over 12 years
    @Paul: you can take a screenshot of a minimized window with PrintWindow only if it handles correctly WM_PRINT, otherwise you're out of luck.
  • jondinham
    jondinham over 12 years
    i suggest using GetWindowRect instead of GetClientRect to make it work more nicely on windows7 or vista with thick borders
  • Davide Piras
    Davide Piras over 12 years
    well there is a difference, it depends if he wants client area only or whole window. Thanks for pointing this out :)
  • jondinham
    jondinham over 12 years
    @davide: the code above can take fully detailed screenshot of some windows like Chrome, Notepad, etc. but with some others like Visual Studio IDE window, etc. some parts of the screenshot is totally black! what happened?
  • M Katz
    M Katz almost 9 years
    I don't understand the rules for whether you should delete a handle after adding it to the clipboard. If you create the handle with GlobalAlloc() the clipboard owns it and you don't delete it. But if it's an HBITMAP as in this example you do delete it?
  • peterh
    peterh over 8 years
    On my opinion it is enough to be an answer, although not a really long one.