Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebBrowser.DrawToBitmap() or other methods?

Tags:

I am trying to capture the content of the WebBrowser control. DrawToBitmap() would work perfectly, but it is not supported in documentation for the WebBrowser control. I have been trying to find another way to capture the contents of the WebBrowser control and save them to a local image file.

Does anyone have any workarounds or other methods to save the contents of the WebBrowser control to a local image file?

like image 838
Matt Avatar asked Mar 12 '10 16:03

Matt


1 Answers

The Control.DrawToBitmap doesn't always work so I resorted to the following native API calls that provide more consistent results:

The Utilities class. Call Utilities.CaptureWindow(Control.Handle) to capture a specific control:

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;     } } 

The Gdi32 class:

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); } 

The User32 class:

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); } 

The constants used:

    public const int SRCCOPY = 13369376; 

The structs used:

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

A friendly Control extension method:

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

This is a code snippet from my CC.Utilities project and I specifically wrote it to take screenshots from the WebBrowser control.

like image 194
Cory Charlton Avatar answered Jan 06 '23 14:01

Cory Charlton