截图方法生成黑色图像

Mse*_*ing 2 c# browser screenshot bitmap windows-7

在 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());
            }
        }
Run Code Online (Sandbox Code Playgroud)

这在用户帐户上运行良好,但是一旦我切换用户,它就会返回异常:句柄无效。

有任何想法吗?

编辑2:

DrawToBitmap 中的错误不是完全随机的...如果我使用您提供的代码:

Bitmap bmp = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height);
this.DrawToBitmap(bmp, this.ClientRectangle);
bmp.Save(".\\picture.jpg");
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

((Control)webbrowser1).Enabled = false;
Run Code Online (Sandbox Code Playgroud)

这使得在网络浏览器上无法进行任何点击,但不幸的是,停用它会使我的项目变得无用,因为它的主要功能是在网络浏览器控件上模拟鼠标点击。尽管如果窗口被隐藏,这也可能是一个问题。

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

模拟点击进入一个隐藏的窗口, 它似乎有一定的价值...看看吧。

TaW*_*TaW 5

您在使用 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();
Run Code Online (Sandbox Code Playgroud)

这是截取窗口屏幕截图的代码:

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();
Run Code Online (Sandbox Code Playgroud)

我可以随意切换用户,程序继续运行。

BTW,你贴的链接真的很旧,很多东西可能已经改进了。

编辑:

有了更新的问题,事情就清楚多了。

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

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

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

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

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

这些问题进来可以预见,当用户交互WebBrowser任何方式。这包括在导航或不导航的情况下滚动或单击。在这些交互之后,WebBrowser它将把自己画成一个空框,直到它的 URL 被重新加载 - 不仅刷新 - 而且真的被webBrowser1.Uri = new Uri(uriPath). 这可以做到,请参阅我的另一篇文章

WebBrowser做的时候也有另外一个问题DrawToBitmap:它会失败(与上述空箱),为包括任何网页<input type="text"元素。我不确定解决这个问题的最佳方法是什么,更不用说为什么它首先发生了..屏幕截图方法没有那个特定的问题。

编辑2:

OP 挖出的代码,使用调用PrintWindow,似乎解决了我们遇到的所有问题:它在注销时工作,即使在单击后也可以使用 Refeshing 并抓取WebBrowser所有页面,包括具有文本输入字段的页面。万岁!

在减少松弛之后,这里是一个版本,可以创建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;
}
Run Code Online (Sandbox Code Playgroud)