1

I'm trying to save a panel control as a bitmap using the following code (VB.net):

Private Sub SaveFileDialog1_FileOk(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles SaveFileDialog1.FileOk
     filename = SaveFileDialog1.FileName
     Dim CardImg As New Bitmap(Panel1.Width, Panel1.Height)
     Panel1.DrawToBitmap(CardImg, Panel1.ClientRectangle)
     CardImg.Save(filename, System.Drawing.Imaging.ImageFormat.Bmp)
 End Sub

Everything works, except the Web browser control, which is docked in the panel. In the saved bitmap, this control appears as only white space, while everything else in the panel renders out fine. Any ideas?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Derek
  • 799
  • 2
  • 8
  • 17
  • possible duplicate of [WebBrowser.DrawtoBitmap() generating blank images for few sites consistently](http://stackoverflow.com/questions/5351830/webbrowser-drawtobitmap-generating-blank-images-for-few-sites-consistently) – Cody Gray - on strike Feb 16 '12 at 02:32
  • The problem is that the `WebBrowser` control is an ActiveX control, which does not support the `DrawToBitmap` method as per the "Remarks" section of [the documentation](http://msdn.microsoft.com/en-us/library/system.windows.forms.control.drawtobitmap.aspx). – Cody Gray - on strike Feb 16 '12 at 02:33
  • 1
    Use IHTMLElementRender: http://social.msdn.microsoft.com/Forums/en-US/winforms/thread/6354ec94-503b-45b6-be2f-94bbd3bc460a – Hans Passant Feb 16 '12 at 04:01

2 Answers2

0

When I saved snapshots from a WebBrowser I called .Focus() on it after navigating -- and somehow the white picture results magically disapperard. Don't know why, but it worked for me.

Gábor Imre
  • 5,899
  • 2
  • 35
  • 48
-1

Download "ScreenCapture.vb" from http://www.vbforums.com/showthread.php?t=385497, use CaptureDeskTopRectangle but you should not use the location of your panel because it's referenced to panel parent you should use yourpanel.PointToScreen() to identify the correct rectangle. Regards..

UPDATE:

Check this out, you gon like it, i similute your case and it's working:

Private Sub btnBrowse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBrowse.Click
        Try
            Using fl As New SaveFileDialog
                fl.Filter = "PNG images|*.png"
                If fl.ShowDialog = Windows.Forms.DialogResult.OK Then
                    Dim sc As New screencapture
                    Dim pt = WebBrowser1.Parent.PointToScreen(WebBrowser1.Location)
                    Dim rec As New Rectangle(pt.X, pt.Y, WebBrowser1.Width, WebBrowser1.Height)
                    Application.DoEvents()
                    Threading.Thread.Sleep(500)
                    Using bmp As Bitmap = sc.CaptureDeskTopRectangle(rec, WebBrowser1.Width, WebBrowser1.Height)
                        bmp.Save(fl.FileName, System.Drawing.Imaging.ImageFormat.Png)
                    End Using
                End If
            End Using
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
    End Sub

Update 2:

In Form:

Private Sub btnBrowse_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBrowse.Click
        Try
            Using fl As New SaveFileDialog
                fl.Filter = "PNG images|*.png"
                If fl.ShowDialog = Windows.Forms.DialogResult.OK Then
                    JSsetTimeout.SetTimeout(Me, "TakeShot", 1500, fl.FileName)
                End If
            End Using
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
End Sub

Sub TakeShot(ByVal FilePath As String)
        Try
            Application.DoEvents()
            Dim sc As New screencapture
            Dim pt = WebBrowser1.Parent.PointToScreen(WebBrowser1.Location)
            Dim rec As New Rectangle(pt.X, pt.Y, WebBrowser1.Width, WebBrowser1.Height)
            Using bmp As Bitmap = sc.CaptureDeskTopRectangle(rec, WebBrowser1.Width, WebBrowser1.Height)
                bmp.Save(FilePath, System.Drawing.Imaging.ImageFormat.Png)
            End Using
        Catch ex As Exception
            MsgBox(ex.Message)
        End Try
End Sub

To Create a time delay add the class below :

Public Class JSsetTimeout

    Public res As Object = Nothing
    Dim WithEvents tm As Timer = Nothing
    Dim _MethodName As String
    Dim _args() As Object
    Dim _ClassInstacne As Object = Nothing

    Public Shared Sub SetTimeout(ByVal ClassInstacne As Object, ByVal obj As String, ByVal TimeSpan As Integer, ByVal ParamArray args() As Object)
        Dim jssto As New JSsetTimeout(ClassInstacne, obj, TimeSpan, args)
    End Sub

    Public Sub New(ByVal ClassInstacne As Object, ByVal obj As String, ByVal TimeSpan As Integer, ByVal ParamArray args() As Object)
        If obj IsNot Nothing Then
            _MethodName = obj
            _args = args
            _ClassInstacne = ClassInstacne
            tm = New Timer With {.Interval = TimeSpan, .Enabled = False}
            AddHandler tm.Tick, AddressOf tm_Tick
            tm.Start()
        End If
    End Sub

    Private Sub tm_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles tm.Tick
        tm.Stop()
        RemoveHandler tm.Tick, AddressOf tm_Tick
        If Not String.IsNullOrEmpty(_MethodName) AndAlso _ClassInstacne IsNot Nothing Then
            res = CallByName(_ClassInstacne, _MethodName, CallType.Method, _args)
        Else
            res = Nothing
        End If
    End Sub
End Class
Amen Ayach
  • 4,288
  • 1
  • 23
  • 23
  • I'm able to draw the webBrowser control to the bitmap using WebBrowser.DrawToBitmap(CardImg, WebBrowser.ClientRectangle). However, this causes the browser's image to be drawn in the corner of the bitmap. How to I set where in the destination image to draw the control? – Derek Feb 17 '12 at 01:11
  • Also, using the method you used doesn't make a whole lot of sense. A little more clarification would be great. Plus, capturing the screen causesit to also capture the Save As dialog box which is still over the panel. – Derek Feb 17 '12 at 01:32
  • This appears to work, as does the ScreenCapture class with a little bit of testing. The problem is that these capturing methods capture the SaveFileDialog box on top top of the program. Is there a way to delay the execution of code until the dialog box is closed? I tried System.Threading.Sleep but that doesn't work. – Derek Feb 22 '12 at 15:08
  • It's weird because it's working with maybe my pc is faster, any way, i developped a special class to create delay, so please check **update 2** and mark my answer as **Right** – Amen Ayach Feb 22 '12 at 18:37