但如果我尝试使用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个性化对话框),我得到的内容大致类似于第二个窗口.但边界仍然缺失.
我还没有找到解决方案,但它能够深入了解问题.
如果你想要抓住屏幕上显示的窗口,只需从桌面窗口句柄(GetDesktopWindow())中将其视为blt,然后只显示包含窗口的矩形.
透明度是窗口抓取的问题.捕获现代Windows操作系统的窗口是不可能的,因为没有支持幻想的图像文件类型,如模糊底层图像.但是,可以将简单的透明度捕获到PNG文件中.
假设窗口看起来最好,请注意屏幕上显示的内容.根据下面的内容,这可能不是真的.复制下面的内容可能也是一个坏主意,因为它可能不会被制裁出现在图像中,就像在Excel的屏幕截图下出现在业务演示文稿中的显式背景图像一样.
如果您从桌面上移开,则复制您在屏幕上看到的内容,包括任何覆盖的窗口和底层窗口(透明的地方).与PrintWindow一样,它通常被认为是“更清洁”,但是你可能想要在你选择的背景上合成它,比如白色或蓝色.如果你想从屏幕上看,有一些方法可以暂时隐藏覆盖目标的窗口,但这是与EnumWindows等一系列工作.
正确地抓取窗口并不是Windows中的一项简单任务,并且有很多屏幕抓取应用程序因为它们如何处理这个问题而相互竞争.此外,在Windows中,有几种方法可以使窗口区域透明,并且它们也可以一起使用.
此外,在Vista中,还有DWM thumbnail API,它允许您获取窗口上绘制的应用程序窗口的副本.有关演示和源代码,请参阅ShareX(以前称为zScreen).
最后,您可以查看Open Broadcaster Software的源代码,它使用Direct3D进行屏幕抓取.