Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PrintWindow() could not print Google Chrome window (Chrome_WidgetWin_1)

I am using Microsoft Visual Studio 2010 and Windows 7 Professional. This is my code to copy window image to clipboard:

void PrintWindowEx( HWND hWnd )
{
    HDC hDCMem = CreateCompatibleDC(NULL);
    RECT rect;

    GetWindowRect(hWnd, &rect);

    HBITMAP hBmp = NULL;

    HDC hDC = GetDC(hWnd);

    hBmp = CreateCompatibleBitmap(hDC, rect.right - rect.left, rect.bottom - rect.top);

    HGDIOBJ hOld = SelectObject(hDCMem, hBmp);
    PrintWindow(hWnd, hDCMem, 0);

    SelectObject(hDCMem, hOld);
    DeleteObject(hDCMem);

    OpenClipboard(hWnd);

    EmptyClipboard(); 
    SetClipboardData(CF_BITMAP, hBmp);
    CloseClipboard();

    ReleaseDC(hWnd, hDC);
}

It works fine with all windows except Google Chrome main window. I thought that it was because Chrome uses direct rendering, so I have disabled hardware acceleration in chrome://settings. Still does not work. Then I realized that working with messages can be limited due to restrictions in Chrome Sandbox, so I started Chrome with --no-sandbox command line option. Still does not work.

How can I get this to work? For Chrome and any other windows like Chrome. BitBlt() is not acceptable because window some parts of the window may be overlapped by another windows, window can be on other desktop, etc. Is there any working solution? Maybe with DLL loading to another process or something like that.

UPD: It does redraw after RedrawWindow(); so I can take screenshot (some parts - left part (width ~20px) and right part are not copied). So, does it support WM_PRINT or not? How can I take full screenshot of the window?

like image 903
cls Avatar asked Jun 21 '15 14:06

cls


2 Answers

I was stuck for ages on this, then found that I can pass a parameter of PW_RENDERFULLCONTENT as the last parameter to PrintWindow. Googling that shows it's new in Windows 8.1 so presumably doesn't work on 7. It may be worth trying it though, Winuser.h defines it as

#if(_WIN32_WINNT >= 0x0603)
#define PW_RENDERFULLCONTENT    0x00000002
#endif /* _WIN32_WINNT >= 0x0603 */
like image 150
Geoff Avatar answered Sep 28 '22 12:09

Geoff


PrintWindow works by sending a WM_PRINT or WM_PRINTCLIENT to the target window. While DefWindowProc handles WM_PRINT for standard window classes, custom window classes must handle WM_PRINT in order for PrintWindow to produce the desired result. If Chrome doesn't handle WM_PRINT or WM_PRINTCLIENT, there's nothing you can do.

When targeting Windows Vista and above you can use the DWM Thumbnail API to force a window to render its contents into a target window provided by the client.

like image 39
IInspectable Avatar answered Sep 28 '22 12:09

IInspectable