【问题标题】:Capturing a hidden window in Vista在 Vista 中捕获隐藏的窗口
【发布时间】:2009-04-12 11:35:14
【问题描述】:

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

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

我在 Delphi 中执行此操作,但任何语言的代码都足够了。

【问题讨论】:

    标签: delphi windows-vista screen-capture


    【解决方案1】:

    我相信当这些窗口不在屏幕上时,这些缓冲区不存在。或者在部分离屏时仅部分存在。

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

    【讨论】:

    • 缓冲区肯定在那里,并且正在更新。开始播放视频,用另一个窗口覆盖它,将鼠标悬停在工具栏上,您会得到正在播放视频的缩略图。
    • 是的,当窗口被覆盖时,而不是当它被最小化时。我以前用 Windows Media Player 试过这个。
    • 此外,似乎从 Windows 7 开始,应用程序可以随意更新其缩略图,而无需依赖 WM_PAINT(由于 GDI 的限制,最小化窗口不会触发它)。 Windows Media Player 12 使用它来继续播放视频,即使在最小化时也是如此。
    • 不幸的是,这是正确的。即使编写自己的视频驱动程序也不允许您捕获窗口内容。
    【解决方案2】:

    这是我很久以前用 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);
    }
    

    【讨论】:

      【解决方案3】:

      【讨论】:

        【解决方案4】:

        你考虑过挂钩 wm_paint 消息吗? 《Windows图形编程:Win32 GDI与DirectDraw》作者冯远为此制作了示例dll。我认为通过这种方式也可以捕获 DirectXed 窗口(随时都有缓冲屏幕)。 请参考http://www.fengyuan.com/article/wmprint.html 你可以通过谷歌找到工作的德尔福例子。还要检查 expterts-exchange.com

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            【解决方案6】:

            执行此操作 (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;
                }
            

            【讨论】:

              猜你喜欢
              • 2010-10-24
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-04-14
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多