tags:

views:

661

answers:

7

I need to copy the content of a window (BitBlt) which is hidden, to another window. The problem is that once I hide the source window, the device context I got isn't painted anymore.

A: 

Maybe you can trigger a redraw operation on the window with InvalidateRect?

HS
+1  A: 

Copy the source bitmap to a memory bitmap before closing/hiding the window.

slashmais
A: 

You could try sending a WM_PRINT message to the window. For many windows (including all standard windows and common controls) this will cause it to paint into the supplied DC.

Also, if you pass an HDC as the wparam of a WM_PAINT message, many windows (such as the common controls) will paint into that DC rather than onto the screen.

Anthony Williams
A: 

Unfortunately, I think you're going to have real problems getting this to work reliably. You don't say exactly what you're doing, but I assume that, given the window handle, you're grabbing the device context associated with the window by calling GetWindowDC(), and then using the resulting device context.

This will work okay on XP when the window is visible. However, on Vista, if desktop compositing is enabled, it won't even work properly then: you'll get 0 back from GetWindowDC(). Fundamentally, grabbing window device contexts isn't going to work reliably.

If the window you're trying to copy from is part of your own application, I'd suggest modifying your code to support the WM___PRINT message: this acts like WM_PAINT, but allows you to supply a device context to draw into.

If the window isn't from your application, you're basically out of luck: if the window is hidden, the image of what it would show if it were visible doesn't exist anywhere.

DavidK
+1  A: 

What you need is the PrintWindow function that's available in Win32 API since Windows XP. If you need it to work with older versions of Windows, you can try WM_PRINT, although I've never been able to make it work.

There's a nice article here that shows how to use PrintWindow, and here's the relevant code snippet from that article:

// Takes a snapshot of the window hwnd, stored in the memory device context hdcMem
HDC hdc = GetWindowDC(hwnd);
if (hdc)
{
    HDC hdcMem = CreateCompatibleDC(hdc);
    if (hdcMem)
    {
        RECT rc;
        GetWindowRect(hwnd, &rc);

        HBITMAP hbitmap = CreateCompatibleBitmap(hdc, RECTWIDTH(rc), RECTHEIGHT(rc));
        if (hbitmap)
        {
            SelectObject(hdcMem, hbitmap);

            PrintWindow(hwnd, hdcMem, 0);

            DeleteObject(hbitmap);
        }
        DeleteObject(hdcMem);
    }
    ReleaseDC(hwnd, hdc);
}

I should have some Python code that uses wxPython to achieve the same thing. Drop me a note if you want it.

gooli
I've always wondered if PrintWindow() uses its own logic, or if it just posts a WM_PRINT to the given window. MSDN seems to be vague on that point. Time for a test program to check that ...
DavidK
It uses its own logic, not WM_PRINT.
Mo Flanagan
A: 

The PrintWindow function doesn't seem to work on a hidden window, only on visible ones.

A: 

Approaching things from a different perspective, are you sure that's really what you want to be doing? You don't, for example, want to be using CreateCompatibleDC and CreateCompatibleBitmap to create your invisible drawing surface, drawing on that and then using BitBlt?

Some more information about the background to what you're up to might enable someone to come up with either a solution or some lateral thinking...

Jon Bright