截图方法生成黑色图像

在c#中未能使用control.drawtobitmap之后,我的第二个选择是获取桌面的屏幕截图并裁剪出所需的部分。 一旦我切换用户帐户,我的打嗝就出现了,虽然程序没有崩溃,一旦用户切换,程序只生成纯黑图像。

我用这个代码作为参考: WebBrowser.DrawToBitmap()或其他方法?

我认为逻辑上这是有道理的,因为这将有助于Windows节省资源。

在我的情况下,我有哪些选择/解决方案?

编辑1对代码进行了修改以进行测试:

int c = 0; while (true) { try { c++; Rectangle formBounds = this.Bounds; Bitmap bmp = new Bitmap(formBounds.Width, formBounds.Height); using (Graphics g = Graphics.FromImage(bmp)) g.CopyFromScreen(formBounds.Location, Point.Empty, formBounds.Size); bmp.Save("picture" + c.ToString() + ".jpg"); Thread.Sleep(5000); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } 

这在用户帐户上完美运行,但是一旦我切换用户,它就会返回exception:句柄无效。

有任何想法吗?

编辑2:

DrawToBitmap中的错误并不是随机的…如果我使用了您提供的代码:

 Bitmap bmp = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height); this.DrawToBitmap(bmp, this.ClientRectangle); bmp.Save(".\\picture.jpg"); 

它完美地运作,例如: http : //oi61.tinypic.com/1z23ynp.jpg

但是,当我右键单击Web浏览器控件时,DrawToBitmap将返回一个空白图像。

例如: http : //oi60.tinypic.com/9ay0yc.jpg

所以我可以通过添加来轻松克服这个错误

 ((Control)webbrowser1).Enabled = false; 

这使得在网络浏览器上无法点击任何内容,但不幸的是,停用它会使我的项目无用,因为它的主要function是模仿Web浏览器控件上的鼠标点击。 虽然如果窗口被隐藏,这也可能是一个问题。

目前我正在看这篇文章,其中提供了代码以提供窗口句柄。

模拟点击进入一个隐藏的窗口似乎它可能有一些价值…看看。

你对DrawToBitmap有什么问题? 它在这里工作正常,(W8.1,VS2013)即使使用Webcontrol也可以在切换用户之后。 (但最后请看条件的编辑!)

 Bitmap bmp = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height); this.DrawToBitmap(bmp, this.ClientRectangle); // Clipboard.SetImage(bmp); for testing only bmp.Dispose(); 

以下是获取窗口截图的代码:

 Rectangle formBounds = this.Bounds; Bitmap bmp = new Bitmap(formBounds.Width, formBounds.Height ); using (Graphics g = Graphics.FromImage(bmp)) g.CopyFromScreen(formBounds.Location, Point.Empty, formBounds.Size); //Clipboard.SetImage(bmp); for testing only bmp.Dispose(); 

我可以像我想的那样切换用户,程序一直在工作。

顺便说一句,你发布的链接真的很旧,很多东西可能都有所改进。

编辑:

随着更新的问题,事情要清楚得多。

因此,即使用户已更改,您也希望不断获取程序的屏幕截图,对吧? 而你想显示一个WebControl,对吧?

用户可以有三种类型的桌面:登录/注销屏幕,屏幕保护程序屏幕和一个或多个普通桌面屏幕。 但是当用户注销时,他根本没有桌面屏幕。

因此,如果用户没有活动桌面,屏幕截图方法将不起作用,既不会像g.CopyFromScreen那样导致GDI错误,也不会像在网络上的各种解决方案中那样使用窗口句柄,包括链接所导致的那些。 所有这些最多只会显示一个空白或黑屏。

所以DrawToBitmap方法是唯一有效的方法。

你写道它有随机错误。 那不是我看到的。

当用户以任何方式与WebBrowser 交互时,问题就会出现。 这包括滚动或点击带或不带导航。 在这些交互之后, WebBrowser将自己绘制为一个空框,直到其URL被重新加载 – 不仅刷新 – 而且实际上由webBrowser1.Uri = new Uri(uriPath)重新加载。 这可以完成,请参阅我的其他post

WebBrowser在执行DrawToBitmap时还有另一个问题:对于包含元素的任何页面,它将失败(使用所述空框)。 我不确定解决此问题的最佳方法是什么,更不用说为什么它首先发生了..截图方法没有那个具体问题。

编辑2:

OP挖出代码的代码,通过调用PrintWindow ,似乎解决了我们遇到的所有问题:它在注销时工作,即使在单击WebBrowser并刮擦所有页面(包括带有文本输入的页面)后也可以使用Refeshing领域。 Hoorah!

在减少松弛之后,这里有一个版本可以创建Form的副本,或者只是带有或不带边框的WebBroser (或任何其他Control ):

 [DllImport("user32.dll")] public static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, uint nFlags); public Bitmap CaptureWindow(Control ctl) { //Bitmap bmp = new Bitmap(ctl.Width, ctl.Height); // includes borders Bitmap bmp = new Bitmap(ctl.ClientRectangle.Width, ctl.ClientRectangle.Height); // content only using (Graphics graphics = Graphics.FromImage(bmp)) { IntPtr hDC = graphics.GetHdc(); try { PrintWindow(ctl.Handle, hDC, (uint)0); } finally { graphics.ReleaseHdc(hDC); } } return bmp; } 

最后,即使我切换了用户,这段代码似乎也能正常工作。

用于截取任何未保存的记事本进程的屏幕截图的代码(“Un​​titled – Notepad”)

  private void Form1_Load(object sender, EventArgs e) { //loop for debugging int c = 0; while(true) { c++; System.Drawing.Bitmap image = CaptureWindow(FindWindow(null, "Untitled - Notepad")); image.Save(".\\picture"+c.ToString()+".jpg"); Thread.Sleep(5000); } } [DllImport("user32.dll")] public static extern bool PrintWindow(IntPtr hwnd, IntPtr hdcBlt, uint nFlags); [DllImport("user32.dll")] public static extern IntPtr GetWindowDC(IntPtr hWnd); [DllImport("user32.dll", SetLastError = true)] static extern IntPtr FindWindow(string lpClassName, string lpWindowName); public System.Drawing.Bitmap CaptureWindow(IntPtr hWnd) { System.Drawing.Rectangle rctForm = System.Drawing.Rectangle.Empty; using (System.Drawing.Graphics grfx = System.Drawing.Graphics.FromHdc(GetWindowDC(hWnd))) { rctForm = System.Drawing.Rectangle.Round(grfx.VisibleClipBounds); } System.Drawing.Bitmap pImage = new System.Drawing.Bitmap(rctForm.Width, rctForm.Height); System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(pImage); IntPtr hDC = graphics.GetHdc(); try { PrintWindow(hWnd, hDC, (uint)0); } finally { graphics.ReleaseHdc(hDC); } return pImage; } 

请注意,窗口可能是隐藏的,但仍必须在用户帐户上最大化才能获得完整的屏幕截图。

数字版权管理可能会阻止这一点,因为Windows增加了对数字媒体的保护。

例如,如果您尝试使用Microsoft的图形渲染在Media Player或Media Center中创建某些内容的屏幕截图 – 是的,Microsoft将“保护您免受任何潜在的诉讼”。

试试这个:点击键盘上的“Print Screen”,然后进入Microsoft Paint并尝试将屏幕截图粘贴到其中。 有什么吗?