Find the rendered image memory address of a Webbrowser Control

Answered Find the rendered image memory address of a Webbrowser Control

  • Wednesday, June 25, 2008 2:31 PM
     
     

    I have been using IHTMLElement2 for quite some time to thumbnail a WebBrowser screen’s image and it works fine…except now xsl/xml rendered HTML is not available in IHTMLElemen2.  I have developed code to go after the memory address of the Desktop Window and have successfully thumb nailed the desktop screen from memory with a form on it hosting a WebBrowser control on it.  This is not a screen scrap or copy from screen operation I have the desktop windows memory address and I am using StretchBlt from that address in memory to a thumbnail.

     

    Being able to use IHTMLElement2 to thumbnail WebBrowser control's HTML allows me to create thumbnails of hosted webBrowser without displaying them.  This is what I am looking to do only now from finding the address where webBrowser controls are fully rendered in memory.   

     

     

    I thought I could just use Me.WebBrowser1.handle and that would point to where the rendered HTML lives… but that did not work.

     

    The following code below works fine for the Desktop window:  Below this code snippet is the original code using IHTMLElement2.

     

    Try

     

                'Handle for the desktop window

                Dim AddrDesktopWindow As IntPtr

                If AddrDesktopWindow = 0 Then AddrDesktopWindow = GetDesktopWindow

     

                'getWindow Size

                Dim rcWindow As RECT

                GetWindowRect(AddrDesktopWindow, rcWindow)

                Dim WinHeight As Integer = rcWindow.Right - rcWindow.Left

                Dim WinWidth As Integer = rcWindow.Bottom - rcWindow.Top

     

                Dim PB1 As Graphics = Me.PictureBox1.CreateGraphics

                Dim AddrOfPB1 As IntPtr = PB1.GetHdc

     

                Dim AddrOfPictureBox1 As IntPtr = Me.PictureBox1.Handle

     

                'create a compatible DC

                Dim AddrCreateCompatibleDC As IntPtr = CreateCompatibleDC(IntPtr.Zero)

     

                'create a memory bitmap in the DC just created, the size of the window we're capturing

                Dim AddrCreateCompatibleBitmap As IntPtr = CreateCompatibleBitmap(AddrOfPB1, WinWidth, WinHeight)

     

                'Prepare DC as a Bitmap using selectObject to configure the DC

                SelectObject(AddrCreateCompatibleDC, AddrCreateCompatibleBitmap)

     

                'copy the screen image into the DC

                BitBlt(AddrCreateCompatibleDC, 0, 0, WinWidth, WinHeight, GetWindowDC(AddrDesktopWindow), 0, 0, SRCCOPY)

     

               'copy DC to the screen

    StretchBlt(AddrOfPB1, 0, 0, 100, 100, AddrCreateCompatibleDC, 0, 0, WinWidth, WinHeight, TernaryRasterOperations.SRCCOPY)

     

                PB1.ReleaseHdc(AddrOfPB1)

                CType(PB1, IDisposable).Dispose()

                DeleteDC(AddrCreateCompatibleDC)

                DeleteObject(AddrCreateCompatibleBitmap)

     

            Catch ex As System.NullReferenceException

                MsgBox("--- NullReferenceException ---" & "  " & _

                vbCrLf & "Message --- " & ex.Message & "  " & _

                vbCrLf & "Source --- " & ex.Source & "  " & _

                vbCrLf & "StackTrace --- " & ex.StackTrace & "  " & _

                vbCrLf & "TargetSite --- " & ex.TargetSite.ToString)

                ' Code reacting to NullReferenceException

            Catch ex As Exception

                ' Code reacting to any exception

                MsgBox(vbCrLf & "Message --- " & ex.Message & "  " & _

                vbCrLf & "Source --- " & ex.Source & "  " & _

                vbCrLf & "StackTrace --- " & ex.StackTrace & "  " & _

                vbCrLf & "TargetSite --- " & ex.TargetSite.ToString)

            End Try

        End Sub

    ORIGINAL CODE:

     

    Try

    Dim document As mshtml.IHTMLDocument2 = DirectCast(Me.WebBrowser1.Document.DomDocument, mshtml.IHTMLDocument2)

    Dim element As mshtml.IHTMLElement2 = DirectCast(document.body, mshtml.IHTMLElement2)

    Dim render As IHTMLElementRender = DirectCast(element, IHTMLElementRender)

    Dim GraphicsObject As Graphics = Me.PictureBox1.CreateGraphics

    Dim PointerToGraphics As IntPtr = GraphicsObject.GetHdc

    Dim PointerToDC As IntPtr = CreateCompatibleDC(IntPtr.Zero)

    Dim PointerToBitmap As IntPtr = CreateCompatibleBitmap(PointerToGraphics, Me.WebBrowser1.Width, Me.WebBrowser1.Height)

    SelectObject(PointerToDC, PointerToBitmap)

    render.DrawToDC(PointerToDC)

    GraphicsObject.ReleaseHdc(PointerToGraphics)

    'Dim dummyCallBack As System.Drawing.Image.GetThumbnailImageAbort

    'dummyCallBack = New System.Drawing.Image.GetThumbnailImageAbort(AddressOf ThumbnailCallback)

    Dim fullSizeImg As System.Drawing.Image

    fullSizeImg = System.Drawing.Image.FromHbitmap(PointerToBitmap)

    Me.PictureBox1.Image = fullSizeImg.GetThumbnailImage(100, 100, Nothing, IntPtr.Zero)

     

    'Cleanup

    CType(GraphicsObject, IDisposable).Dispose()

    DeleteDC(PointerToDC)

    DeleteObject(PointerToBitmap)

    Catch ex As System.NullReferenceException

    MsgBox("--- NullReferenceException ---" & " " & _

    vbCrLf & "Message --- " & ex.Message & " " & _

    vbCrLf & "Source --- " & ex.Source & " " & _

    vbCrLf & "StackTrace --- " & ex.StackTrace & " " & _

    vbCrLf & "TargetSite --- " & ex.TargetSite.ToString)

    ' Code reacting to NullReferenceException

    Catch ex As Exception

    ' Code reacting to any exception

    MsgBox(vbCrLf & "Message --- " & ex.Message & " " & _

    vbCrLf & "Source --- " & ex.Source & " " & _

    vbCrLf & "StackTrace --- " & ex.StackTrace & " " & _

    vbCrLf & "TargetSite --- " & ex.TargetSite.ToString)

    End Try

     

All Replies

  • Monday, June 30, 2008 2:25 AM
     
     
    You want IViewObject :: Draw().

     

  • Tuesday, July 01, 2008 1:23 PM
     
     

    I tried using Draw But I couldn't quite figure what Parms were needed to Draw the HTML to a device context

     

    'create a compatible DC

    Dim AddrCreateCompatibleDC As IntPtr = CreateCompatibleDC(IntPtr.Zero)

     

    'create a memory bitmap in the DC just created, the size of the window we're capturing

    Dim AddrCreateCompatibleBitmap As IntPtr = CreateCompatibleBitmap(AddrOfPB1, WinWidth, WinHeight)

     

    'Prepare DC as a Bitmap using selectObject to configure the DC

    SelectObject(AddrCreateCompatibleDC, AddrCreateCompatibleBitmap)

     

    Now Draw to the device context...

     

    <Guid("0000010D-0000-0000-C000-000000000046")> <InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown), ComVisible(True), ComImport()> _

    Interface IViewObject

    Sub Draw(ByVal dwDrawAspect As UInteger, _

    ByVal lindex As Integer, _

    ByVal pvAspect As UInteger, _

    ByVal ptd() As Microsoft.VisualStudio.OLE.Interop.DVTARGETDEVICE, _

    ByVal hdcTargetDev As UInteger, ByVal hdcDraw As UInteger, _

    ByVal lprcBounds() As Microsoft.VisualStudio.OLE.Interop.RECTL, _

    ByVal lprcWBounds() As Microsoft.VisualStudio.OLE.Interop.RECTL, _

    ByVal pContinue As Microsoft.VisualStudio.OLE.Interop.IContinue)

    End Interface

  • Tuesday, July 01, 2008 6:23 PM
     
     
    My VB-fu is weak.  Sad
  • Wednesday, July 02, 2008 4:48 AM
     
     Answered

    OK, I FINALLY GOT IT TO WORK…..OFFSCREEN with SilverLight and XSL/XML or anything else!

     

    After looking at WinDbg and screwing around with memory addresses.  I finally got it to write off screen using IViewObject Draw function to a DC and then to a thumbnail.  What a pain this was!

     

    I had to use StretchBlt to grab it from the DC to shrink it down to a 100 by 100 thumbnail.  I do not like the way StretchBlt renders it.  The thumbnail is grainy and not as clear as the original FromBitmap code.  BUT for NOW ENOUGH IS ENOUGH!  I’ll deal with that later…


    The Following CODE will write the rendered HTML screen from its memory location (not the form on the Desktop) and post it to a DEVICE COINTEXT.  It works WITH SILVERLIGHT and XSL/XML.  From the DC I use StretchBlt (will change that) to shrink it to the Picturebox 100 by 100 thumb.

     

    <ComImport(), _
    InterfaceType(ComInterfaceType.InterfaceIsIUnknown), _
    Guid("00000127-0000-0000-C000-000000000046")> _
    Public Interface IViewObject
        Function Draw(ByVal dwDrawAspect As Int32, _
        ByVal lindex As Int32, _
        ByVal pvAspect As IntPtr, _
        ByVal ptd As IntPtr, _
        ByVal hicTargetDev As Int32, _
        ByVal hdcDraw As IntPtr, _
        ByVal prcBounds As IntPtr, _
        ByVal prcWBounds As RectangleF, _
        ByVal fnContinue As IntPtr, _
        ByVal dwContinue As Int32) As Int32
    End Interface

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    Try

                Dim ViewObject As IViewObject = DirectCast(Me.WebBrowser1.Document.DomDocument, IViewObject)

                Dim PB1 As Graphics = Me.PictureBox1.CreateGraphics
                Dim AddrOfPB1 As IntPtr = PB1.GetHdc

                'create a compatible DC
                Dim AddrCreateCompatibleDC As IntPtr = CreateCompatibleDC(IntPtr.Zero)

                'create a memory bitmap in the DC just created, the size of the window we're capturing
                Dim AddrCreateCompatibleBitmap As IntPtr = CreateCompatibleBitmap(AddrOfPB1, Me.WebBrowser1.Width, Me.WebBrowser1.Height)

                'Prepare DC as a Bitmap using selectObject to configure the DC
                SelectObject(AddrCreateCompatibleDC, AddrCreateCompatibleBitmap)

                'Draw the Rendered DomDocument to the Device Context
                ViewObject.Draw(1, 1, Nothing, Nothing, 0, AddrCreateCompatibleDC, Nothing, Nothing, Nothing, 0)

                'Use StretchBlt to shrink it down to the Theubnail
                StretchBlt(AddrOfPB1, 0, 0, 100, 100, AddrCreateCompatibleDC, 0, 0, Me.WebBrowser1.Width, Me.WebBrowser1.Height, TernaryRasterOperations.SRCCOPY)


                'Dim fullSizeImg As System.Drawing.Image
                'fullSizeImg = System.Drawing.Image.FromHbitmap(AddrCreateCompatibleBitmap)

                PB1.ReleaseHdc(AddrOfPB1)
                CType(PB1, IDisposable).Dispose()
                DeleteDC(AddrCreateCompatibleDC)
                DeleteObject(AddrCreateCompatibleBitmap)

            Catch ex As System.NullReferenceException
                MsgBox("--- NullReferenceException ---" & "  " & _
                vbCrLf & "Message --- " & ex.Message & "  " & _
                vbCrLf & "Source --- " & ex.Source & "  " & _
                vbCrLf & "StackTrace --- " & ex.StackTrace & "  " & _
                vbCrLf & "TargetSite --- " & ex.TargetSite.ToString)
                ' Code reacting to NullReferenceException
            Catch ex As Exception
                ' Code reacting to any exception
                MsgBox(vbCrLf & "Message --- " & ex.Message & "  " & _
                vbCrLf & "Source --- " & ex.Source & "  " & _
                vbCrLf & "StackTrace --- " & ex.StackTrace & "  " & _
                vbCrLf & "TargetSite --- " & ex.TargetSite.ToString)
            End Try
      


    End Sub