在Vista中捕获隐藏的窗口

时间:2009-04-12 11:35:14

标签: delphi windows-vista screen-capture

我对Vista的理解是每个窗口都有自己的屏幕缓冲区,然后进行alpha混合等创建屏幕。

那么,有没有办法通过直接读取这些缓冲区来屏幕捕获被遮挡或部分偏离屏幕的窗口?当您使用alt-tab或将鼠标悬停在任务栏上时,Vista会执行此操作。

我在Delphi中这样做,但任何语言的代码就足够了。

6 个答案:

答案 0 :(得分:2)

我认为当这些窗口在屏幕外时,这些缓冲区不存在。部分屏幕外部分或仅部分存在。

如果您注意窗口缩略图,您会发现当这些窗口最小化或屏幕外时它不会更新。 WM_PAINT将在窗口从屏幕外拖到打开时触发,再次表明此数据尚未在某处缓冲。

答案 1 :(得分:0)

这是我很久以前在C#中为屏幕捕获应用程序编写的一些代码。它使用Win32函数GetWindowRect获取要捕获的窗口的边界,创建具有该大小的位图,然后使用Win32函数PrintWindow请求窗口将自己打印到该位图:

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);
}

答案 2 :(得分:0)

答案 3 :(得分:0)

你有没有想过挂钩wm_paint消息? “Windows图形编程:Win32 GDI和DirectDraw”的作者冯媛为此做了样本dll。我认为通过这种方式也可以捕获DirectXed窗口(随时都有缓存屏幕)。 请参阅http://www.fengyuan.com/article/wmprint.html 你可以通过谷歌找到工作的delphi示例。还请检查expterts-exchange.com

答案 4 :(得分:0)

我认为新的DWM APi(桌面Windows管理器)中可能存在一些内容,您可以编写和安装自定义桌面管理器,并可以访问您在Flip3d和其他视图中看到的相同缩略图。

答案 5 :(得分:0)

这样做(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;
    }