在线程中执行 Web 浏览器控件的屏幕视图

本文关键字:控件 屏幕 视图 浏览器 Web 线程 执行 | 更新日期: 2023-09-27 18:30:28

>我正在使用中所示的技术

新线程中的 Web 浏览器控件

尝试获取网页的屏幕抓取,我已经能够获得以下代码,以便在将WebBrowser控件放置在WinForm上时成功工作。但是,当在线程中运行时,它会通过提供桌面的任意图像而失败。

Thread browserThread = new Thread(() =>
{
    WebBrowser br = new WebBrowser();
    br.DocumentCompleted += webBrowser1_DocumentCompleted;
    br.ProgressChanged += webBrowser1_ProgressChanged;
    br.ScriptErrorsSuppressed = true;
    br.Navigate(url);
    Application.Run();
});
browserThread.SetApartmentState(ApartmentState.STA);
browserThread.Start();
private Image TakeSnapShot(WebBrowser browser)
{
    int width;
    int height;
    width = browser.ClientRectangle.Width;
    height = browser.ClientRectangle.Height;
    Bitmap image = new Bitmap(width, height);
    using (Graphics graphics = Graphics.FromImage(image))
    {
        Point p = new Point(0, 0);
        Point upperLeftSource = browser.PointToScreen(p);
        Point upperLeftDestination = new Point(0, 0);
        Size blockRegionSize = browser.ClientRectangle.Size;
        blockRegionSize.Width = blockRegionSize.Width - 15;
        blockRegionSize.Height = blockRegionSize.Height - 15;
        graphics.CopyFromScreen(upperLeftSource, upperLeftDestination, blockRegionSize);
    }
    return image;
}

这显然是由于方法Graphics.CopyFromScreen()而发生的,但我不知道任何其他方法。有没有办法解决这个问题,任何人都可以建议?还是我唯一的选择是创建窗体、添加控件、使其可见,然后进行屏幕抓取?出于显而易见的原因,我希望避免这种方法。

在线程中执行 Web 浏览器控件的屏幕视图

你可以写

private Image TakeSnapShot(WebBrowser browser)
{
     browser.Width = browser.Document.Body.ScrollRectangle.Width;
     browser.Height= browser.Document.Body.ScrollRectangle.Height;
     Bitmap bitmap = new Bitmap(browser.Width - System.Windows.Forms.SystemInformation.VerticalScrollBarWidth, browser.Height);
     browser.DrawToBitmap(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height));
     return bitmap;
}

完整的工作代码

var image = await WebUtils.GetPageAsImageAsync("http://www.stackoverflow.com");
image.Save(fname , System.Drawing.Imaging.ImageFormat.Bmp);

public class WebUtils
{
    public static Task<Image> GetPageAsImageAsync(string url)
    {
        var tcs = new TaskCompletionSource<Image>();
        var thread = new Thread(() =>
        {
            WebBrowser browser = new WebBrowser();
            browser.Size = new Size(1280, 768);
            WebBrowserDocumentCompletedEventHandler documentCompleted = null;
            documentCompleted = async (o, s) =>
            {
                browser.DocumentCompleted -= documentCompleted;
                await Task.Delay(2000); //Run JS a few seconds more
                Bitmap bitmap = TakeSnapshot(browser);
                tcs.TrySetResult(bitmap);
                browser.Dispose();
                Application.ExitThread();
            };
            browser.ScriptErrorsSuppressed = true;
            browser.DocumentCompleted += documentCompleted;
            browser.Navigate(url);
            Application.Run();
        });
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
        return tcs.Task;
    }
    private static Bitmap TakeSnapshot(WebBrowser browser)
    {
         browser.Width = browser.Document.Body.ScrollRectangle.Width;
         browser.Height= browser.Document.Body.ScrollRectangle.Height;
         Bitmap bitmap = new Bitmap(browser.Width - System.Windows.Forms.SystemInformation.VerticalScrollBarWidth, browser.Height);
         browser.DrawToBitmap(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height));
         return bitmap;
    }
}
using (Graphics graphics = Graphics.FromImage(image))
    {
        Point p = new Point(0, 0);
        Point upperLeftSource = browser.PointToScreen(p);
        Point upperLeftDestination = new Point(0, 0);
        Size blockRegionSize = browser.ClientRectangle.Size;
        blockRegionSize.Width = blockRegionSize.Width - 15;
        blockRegionSize.Height = blockRegionSize.Height - 15;
        graphics.CopyFromScreen(upperLeftSource, upperLeftDestination, blockRegionSize);
    }

你真的需要使用语句吗?

您也return image但是如何将复制的图像分配给它?