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.ImagefullSizeImg = 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.NullReferenceExceptionMsgBox(
"--- 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 exceptionMsgBox(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 AMYou 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 PMMy VB-fu is weak.

-
Wednesday, July 02, 2008 4:48 AM
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 InterfacePrivate 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


