代码之家  ›  专栏  ›  技术社区  ›  Matt

webbrowser.drawtobitmap()或其他方法?

  •  22
  • Matt  · 技术社区  · 15 年前

    我试图捕获WebBrowser控件的内容。 DrawToBitmap() 可以很好地工作,但是webbrowser控件的文档不支持它。我一直在尝试另一种方法来捕获webbrowser控件的内容并将其保存到本地图像文件中。

    是否有任何解决方法或其他方法将WebBrowser控件的内容保存到本地图像文件?

    3 回复  |  直到 10 年前
        1
  •  37
  •   Cory Charlton    15 年前

    control.drawtobitmap并不总是起作用,因此我求助于以下提供更一致结果的本机API调用:

    实用程序类。调用Utilities.CaptureWindow(control.handle)以捕获特定控件:

    public static class Utilities
    {
        public static Image CaptureScreen()
        {
            return CaptureWindow(User32.GetDesktopWindow());
        }
    
        public static Image CaptureWindow(IntPtr handle)
        {
    
            IntPtr hdcSrc = User32.GetWindowDC(handle);
    
            RECT windowRect = new RECT();
            User32.GetWindowRect(handle, ref windowRect);
    
            int width = windowRect.right - windowRect.left;
            int height = windowRect.bottom - windowRect.top;
    
            IntPtr hdcDest = Gdi32.CreateCompatibleDC(hdcSrc);
            IntPtr hBitmap = Gdi32.CreateCompatibleBitmap(hdcSrc, width, height);
    
            IntPtr hOld = Gdi32.SelectObject(hdcDest, hBitmap);
            Gdi32.BitBlt(hdcDest, 0, 0, width, height, hdcSrc, 0, 0, ApiConstants.SRCCOPY);
            Gdi32.SelectObject(hdcDest, hOld);
            Gdi32.DeleteDC(hdcDest);
            User32.ReleaseDC(handle, hdcSrc);
    
            Image image = Image.FromHbitmap(hBitmap);
            Gdi32.DeleteObject(hBitmap);
    
            return image;
        }
    }
    

    GDI32类:

    public class Gdi32
    {
        [DllImport("gdi32.dll")]
        public static extern bool BitBlt(IntPtr hObject, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hObjectSource, int nXSrc, int nYSrc, int dwRop);
        [DllImport("gdi32.dll")]
        public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC, int nWidth, int nHeight);
        [DllImport("gdi32.dll")]
        public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
        [DllImport("gdi32.dll")]
        public static extern bool DeleteDC(IntPtr hDC);
        [DllImport("gdi32.dll")]
        public static extern bool DeleteObject(IntPtr hObject);
        [DllImport("gdi32.dll")]
        public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);
    }
    

    user32类:

    public static class User32
    {
        [DllImport("user32.dll")]
        public static extern IntPtr GetDesktopWindow();
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowDC(IntPtr hWnd);
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindowRect(IntPtr hWnd, ref RECT rect);
        [DllImport("user32.dll")]
        public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);
    }
    

    使用的常数:

        public const int SRCCOPY = 13369376;
    

    使用的结构:

    [StructLayout(LayoutKind.Sequential)]
    public struct RECT
    {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }
    

    友好的控制扩展方法:

    public static class ControlExtensions
    {
        public static Image DrawToImage(this Control control)
        {
            return Utilities.CaptureWindow(control.Handle);
        }
    }
    

    这是我的 CC.Utilities 我和project专门写它来从webbrowser控件中截图。

        2
  •  3
  •   Ahmad    10 年前

    以下方法可以捕获整个窗口图像,即使窗口大于屏幕大小。如果窗口大小调整为 webBrowser.Document.OffsetRectangle.Size

    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);
    
        3
  •  0
  •   John Jin    15 年前

    我使用drawtobitmap(visualstudio2008c)来捕获大图像(用户签名的发票,屏幕外的内容)。基本上它工作得很好,但我得到的是空白图像。大约100名员工正在使用这个软件,大约每两周我就可以看到一张空白图片。

    我做了很多测试,我发现一件有趣的事是: 我创建了一个按钮来从webbrowser生成图像。通常是可以的,但是如果我先点击网页浏览器,然后点击创建按钮,空白图像就会出现。