views:

951

answers:

7

My understanding of Vista is that each window gets it's own screen buffer which is then alpha blended etc to create the screen.

So, is there any way to screen capture a window which is obscured or partly off screen by directly reading these buffers? Vista does it when you alt-tab or hover the mouse over the taskbar.

I'm doing this in Delphi, but code in any language will suffice.

+2  A: 

I believe those buffers don't exists when those windows are off-screen. Or only partially exist when partially off-screen.

If you pay attention to the window thumbnails, you will find it will not update when those windows are minimized or off-screen. WM_PAINT will fire as a window is being dragged from off-screen to on, again suggesting that this data was not already buffered somewhere.

Nick Whaley
The buffers are definitely there, and being updated. Start a video playing, cover it with another window, hover over the toolbar and you get a thumbnail of the playing video.
Mike Sutton
Yeh, when the window is covered, but not when it's minimized. I've tried this before with Windows Media Player.
U62
Also, seemingly beginning with Windows 7, applications can update their thumbnail at will without having to rely on WM_PAINT (which won't get fired for minimized windows, as a limitation of GDI). Windows Media Player 12 uses this to continue to play video even when minimized.
Joey
Unfortunately, this is correct. Even writing your own video drover won't allow you to capture the window content.
Joshua
A: 

Here's some code I wrote a long time ago in C# for a screen capture application. It uses the Win32 function GetWindowRect to get the bounds of the window you want to capture, create a bitmap with that size and then use the Win32 function PrintWindow to ask the window to print itself to that bitmap:

RECT lRectangle = new RECT();
if (!GetWindowRect(lWindow.HWnd, ref lRectangle))
{
    MessageBox.Show(this, "An error occured while measuring the selected window.", Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
    return;
}

fCapturedImage = new Bitmap(lRectangle.Right - lRectangle.Left, lRectangle.Bottom - lRectangle.Top, PixelFormat.Format32bppArgb);
using (Graphics lGraphics = Graphics.FromImage(fCapturedImage))
{
    HDC lHdc = lGraphics.GetHdc();
    PrintWindow(lWindow.HWnd, lHdc, 0);
    lGraphics.ReleaseHdc(lHdc);
}
Tommy Carlier
A: 

Anything useful in this thread?: http://www.eggheadcafe.com/conversation.aspx?messageid=31543575&threadid=31543575

dangph
A: 

have u considired hooking wm_paint message ? the author of "Windows Graphics Programming: Win32 GDI and DirectDraw" Feng Yuan made sample dll for that matter . i think with that way it is possible to capture DirectXed windows too (which has is buffred screen anytime). plz refer to http://www.fengyuan.com/article/wmprint.html u can find working delphi examples via google. also check expterts-exchange.com

avar
A: 

I think there might be something in the new DWM APi (Desktop Windows Manager) which let's you write and install custom desktop managers, with access to the same thumbnails you see in the Flip3d and other views.

Marco Cantù
A: 

Do this (C#)

    public static Bitmap PrintWindow(IntPtr hwnd)
    {
        RECT rc;
        WinUserApi.GetWindowRect(hwnd, out rc);

        Bitmap bmp = new Bitmap(rc.Width, rc.Height, PixelFormat.Format32bppArgb);
        Graphics gfxBmp = Graphics.FromImage(bmp);
        IntPtr hdcBitmap = gfxBmp.GetHdc();
        bool succeeded = WinUserApi.PrintWindow(hwnd, hdcBitmap, 0);
        gfxBmp.ReleaseHdc(hdcBitmap);
        if (!succeeded)
        {
            gfxBmp.FillRectangle(new SolidBrush(Color.Gray), new Rectangle(Point.Empty, bmp.Size));
        }
        IntPtr hRgn = WinGdiApi.CreateRectRgn(0, 0, 0, 0);
        WinUserApi.GetWindowRgn(hwnd, hRgn);
        Region region = Region.FromHrgn(hRgn);
        if (!region.IsEmpty(gfxBmp))
        {
            gfxBmp.ExcludeClip(region);
            gfxBmp.Clear(Color.Transparent);
        }
        gfxBmp.Dispose();
        return bmp;
    }
Mo Flanagan
A: 

how do we use this code in C# express?

Lee