加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

windows – PrintWindow位图与PrintScreen Key位图不同

发布时间:2020-12-13 22:42:50 所属栏目:Windows 来源:网络整理
导读:使用Print Screen Alt键组合手动捕获窗口时,我得到以下内容: 但如果我尝试使用Windows API以编程方式进行,我会得到: 为什么会出现差异?我如何以编程方式获得第一个? 这是我的代码: [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)]
使用Print Screen Alt键组合手动捕获窗口时,我得到以下内容:

但如果我尝试使用Windows API以编程方式进行,我会得到:

为什么会出现差异?我如何以编程方式获得第一个?

这是我的代码:

[DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool PrintWindow(IntPtr hWnd,IntPtr hdcBlt,int nFlags);

    public Bitmap PrintWindow()
    {
        Bitmap bmp = new Bitmap(windowRect.Width,windowRect.Height,PixelFormat.Format32bppArgb);
        Graphics gfxBmp = Graphics.FromImage(bmp);
        IntPtr hdcBitmap = gfxBmp.GetHdc();

        bool success = PrintWindow(windowHandle,hdcBitmap,0);
        gfxBmp.ReleaseHdc(hdcBitmap);

        if (!success)
        {
            Console.WriteLine("Error copying image");
            Console.WriteLine(getLastError());
        }

        gfxBmp.Dispose();

        return bmp;
    }

更新:
使用BitBlt做同样的事情.

这是code from CodeProject仍然返回黑色蒙版图像:

public Image CaptureWindow(IntPtr handle)
{
    // get te hDC of the target window
    IntPtr hdcSrc = User32.GetWindowDC(handle);
    // get the size
    User32.RECT windowRect = new User32.RECT();
    User32.GetWindowRect(handle,ref windowRect);
    int width = windowRect.right - windowRect.left;
    int height = windowRect.bottom - windowRect.top;
    // create a device context we can copy to
    IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
    // create a bitmap we can copy it to,// using GetDeviceCaps to get the width/height
    IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc,width,height);
    // select the bitmap object
    IntPtr hOld = GDI32.SelectObject(hdcDest,hBitmap);
    // bitblt over
    GDI32.BitBlt(hdcDest,height,hdcSrc,CopyPixelOperation.SourceCopy | CopyPixelOperation.CaptureBlt);
    // restore selection
    GDI32.SelectObject(hdcDest,hOld);
    // clean up
    GDI32.DeleteDC(hdcDest);
    User32.ReleaseDC(handle,hdcSrc);
    // get a .NET image object for it
    Image img = Image.FromHbitmap(hBitmap);
    // free up the Bitmap object
    GDI32.DeleteObject(hBitmap);

    img.Save("SampleImage.png");
    return img;
}

我尝试了很多CopyPixelOperation的组合(大约有131,000个中的15,000个),但它仍然不起作用.

使用Windows 8,AMD Radeon HD 6870.

更新2

看起来窗户是透明的,允许窗户的蓝色渗透.当我将窗口颜色更改为黑色时(使用Windows个性化对话框),我得到的内容大致类似于第二个窗口.但边界仍然缺失.

我还没有找到解决方案,但它能够深入了解问题.

PrintWindow不起作用的原因是它取决于应用程序正确处理 WM_PRINT消息.很多应用程序都没有WM_PRINT,并且没有正确实现或者测试它.因此,依赖它是一个坏主意,除非你只在已知和测试的应用程序上使用它.

如果你想要抓住屏幕上显示的窗口,只需从桌面窗口句柄(GetDesktopWindow())中将其视为blt,然后只显示包含窗口的矩形.

透明度是窗口抓取的问题.捕获现代Windows操作系统的窗口是不可能的,因为没有支持幻想的图像文件类型,如模糊底层图像.但是,可以将简单的透明度捕获到PNG文件中.

假设窗口看起来最好,请注意屏幕上显示的内容.根据下面的内容,这可能不是真的.复制下面的内容可能也是一个坏主意,因为它可能不会被制裁出现在图像中,就像在Excel的屏幕截图下出现在业务演示文稿中的显式背景图像一样.

如果您从桌面上移开,则复制您在屏幕上看到的内容,包括任何覆盖的窗口和底层窗口(透明的地方).与PrintWindow一样,它通常被认为是“更清洁”,但是你可能想要在你选择的背景上合成它,比如白色或蓝色.如果你想从屏幕上看,有一些方法可以暂时隐藏覆盖目标的窗口,但这是与EnumWindows等一系列工作.

正确地抓取窗口并不是Windows中的一项简单任务,并且有很多屏幕抓取应用程序因为它们如何处理这个问题而相互竞争.此外,在Windows中,有几种方法可以使窗口区域透明,并且它们也可以一起使用.

此外,在Vista中,还有DWM thumbnail API,它允许您获取窗口上绘制的应用程序窗口的副本.有关演示和源代码,请参阅ShareX(以前称为zScreen).

最后,您可以查看Open Broadcaster Software的源代码,它使用Direct3D进行屏幕抓取.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读