将WebBrowser.Document转换为位图?

16

如何将WebBrowser.Document绘制到Bitmap中?基本上是对WebBrowser控件进行截屏(请注意,这个WebBrowser不在窗体上,只存在于代码中)。

WebBrowser w = new WebBrowser();
w.Document = "<b>Hello</b> world.";
w.Document.DrawToBitmap ???

谢谢!


2
我认为@webspy的答案应该被接受为更好的答案。原因是它在浏览器不可见时也能正常工作(甚至可以在屏幕范围之外)。 - Ceco
一个相关的问答:如何在WebBrowser控件上使用DrawToBitmap修复不透明度错误? - noseratio - open to work
4个回答

28
我使用以下代码来截取WebBrowser控件中加载的网页的屏幕截图:
class NativeMethods
{
    [ComImport]
    [Guid("0000010D-0000-0000-C000-000000000046")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    interface IViewObject
    {
        void Draw([MarshalAs(UnmanagedType.U4)] uint dwAspect, int lindex, IntPtr pvAspect, [In] IntPtr ptd, IntPtr hdcTargetDev, IntPtr hdcDraw, [MarshalAs(UnmanagedType.Struct)] ref RECT lprcBounds, [In] IntPtr lprcWBounds, IntPtr pfnContinue, [MarshalAs(UnmanagedType.U4)] uint dwContinue);
    }

    [StructLayout(LayoutKind.Sequential, Pack = 4)]
    struct RECT
    {
        public int Left;
        public int Top;
        public int Right;
        public int Bottom;
    }

    public static void GetImage(object obj, Image destination, Color backgroundColor)
    {
        using(Graphics graphics = Graphics.FromImage(destination))
        {
            IntPtr deviceContextHandle = IntPtr.Zero;
            RECT rectangle = new RECT();

            rectangle.Right = destination.Width;
            rectangle.Bottom = destination.Height;

            graphics.Clear(backgroundColor);

            try
            {
                deviceContextHandle = graphics.GetHdc();

                IViewObject viewObject = obj as IViewObject;
                viewObject.Draw(1, -1, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, deviceContextHandle, ref rectangle, IntPtr.Zero, IntPtr.Zero, 0);
            }
            finally
            {
                if(deviceContextHandle != IntPtr.Zero)
                {
                    graphics.ReleaseHdc(deviceContextHandle);
                }
            }
        }
    }
}

示例:

Bitmap screenshot = new Bitmap(1024, 768);
NativeMethods.GetImage(webBrowser.ActiveXInstance, screenshot, Color.White);

谢谢你提供的代码,它非常好用。但是我遇到了一个奇怪的问题,当我进行渲染时,图片似乎被拉伸和缩放了(图片框本身并没有这样做)。你有什么想法是什么原因导致的吗? - Anonymous
3
答案很简单——使用WebBrowser类的Width/Height方法调整Web浏览器的大小。感谢webspy提供这个巧妙的代码片段。 - Anonymous
非常感谢您的实现,webspy! - Ceco
太棒了!非常感谢! - Peter
1
太好了。你节省了我数小时的工作时间。非常感谢。 - Aishu

2
    public void HTMLScreenShot()
    {
        WebBrowser wb = new WebBrowser();
        wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(wb_DocumentCompleted);
        wb.Size = new Size(800, 600);

        // Add html as string
        wb.Navigate("about:blank");
        wb.Document.Write("<b>Hellow World!</b>");
        // Add html from website
        // wb.Navigate("http://myurl.com");

    }

    void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
    {
        WebBrowser wb = sender as WebBrowser;

        using (Bitmap bitmap = new Bitmap(wb.Width, wb.Height))
        {
            Rectangle bounds = new Rectangle(new Point(0, 0), wb.Size);
            wb.DrawToBitmap(bitmap, bounds);
            bitmap.Save("C:\WebsiteScreenshot.png");
        }
    }

1
//
//   If you want to take a snap from existing webBrowser Control
//

    private void button1_Click(object sender, EventArgs e)
    {
       using (FileDialog fd = new SaveFileDialog())
        {
            fd.Filter = "Image (*.png)|*.png";
            if (fd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                new WebPageSnap(webBrowser1.Url.ToString(), fd.FileName);
                //might take 3 or 4 seconds to save cauz it has to load again.
            }
        }
    }


//
//   Or if you want to take a snap without showing up
//


    private void button2_Click(object sender, EventArgs e)
    {
       using (FileDialog fd = new SaveFileDialog())
        {
            fd.Filter = "Image (*.png)|*.png";
            if (fd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string url = "http://www.google.com";
                // or 
                url = textBox1.Text;
                new WebPageSnap(url, fd.FileName);                }
        }
    }

    class WebPageSnap
    {
        WebBrowser wb;
        string outFile;

        public WebPageSnap(string url, string outputFile)
        {
            wb = new WebBrowser();
            wb.ProgressChanged += wb_ProgressChanged;
            outFile = outputFile;
            wb.ScriptErrorsSuppressed = true;
            wb.ScrollBarsEnabled = false;
            wb.Navigate(url);
        }

        void wb_ProgressChanged(object sender, WebBrowserProgressChangedEventArgs e)
        {
            if (e.CurrentProgress == e.MaximumProgress)
            {
                wb.ProgressChanged -= wb_ProgressChanged;
                try
                {
                    int scrollWidth = 0;
                    int scrollHeight = 0;

                    scrollHeight = wb.Document.Body.ScrollRectangle.Height;
                    scrollWidth = wb.Document.Body.ScrollRectangle.Width;
                    wb.Size = new Size(scrollWidth, scrollHeight);


                    Bitmap bitmap = new Bitmap(wb.Width, wb.Height);
                    for (int Xcount = 0; Xcount < bitmap.Width; Xcount++)
                        for (int Ycount = 0; Ycount < bitmap.Height; Ycount++)
                            bitmap.SetPixel(Xcount, Ycount, Color.Black);
                    wb.DrawToBitmap(bitmap, new Rectangle(0, 0, wb.Width, wb.Height));
                    bitmap.Save(outFile, ImageFormat.Png);
                }
                catch { }
            }
        }

    }

1

你能解释一下“获取WebBrowser控件的句柄”是什么意思吗?谢谢! :) - sooprise

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接