iHTMLElementrender.drawtodc causes error in VB.net application

D

ddd

Hi,

I am having problems with using the DrawToDC of the
MSHTML.iHTMLElementRender in a VB.net application. For some reason I am
getting a "catastrophic error". I am basing the code on c# examples, and I
am not sure what exactly I am doing wrong. From the C# posts it seems that
the drawtodc has a bug and you need to redifine it, so i followed their
advice and specified an interface as below:


Imports System
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports mshtml

<ComVisible(True), ComImport(),
Guid("3050f669-98b5-11cf-bb82-00aa00bdce0b"), _
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Interface IHTMLElementRender
Sub DrawToDC(<[In]()> ByVal hDC As IntPtr)
Sub SetDocumentPrinter(<[In](), MarshalAs(UnmanagedType.BStr)> ByVal
bstrPrinterName As String, <[In]()> ByVal hDC As IntPtr)
End Interface 'IHTMLElementRender

On the main form of the application I am doing the following:

Dim objMSHTML As HTMLDocument
Dim objDocument As IHTMLDocument2
Dim ips As IPersistStreamInit

objMSHTML = New HTMLDocument()

ips = DirectCast(objMSHTML, IPersistStreamInit)
ips.InitNew()

objDocument =
objMSHTML.createDocumentFromUrl("http://www.google.com", String.Empty)

Do Until objDocument.readyState = "complete"
Application.DoEvents()
Loop

MsgBox(objDocument.body.outerHTML)
Dim bodyElement As IHTMLElement
Dim render As IHTMLElementRender


If objDocument.body.outerHTML <> Nothing Then
bodyElement = objDocument.body
render = bodyElement
Dim img As New Bitmap(600, 400)
Dim g As Graphics = Graphics.FromImage(img)
Dim memDC As IntPtr
memDC = g.GetHdc()

Try
render.DrawToDC(memDC)
Catch ex As Exception
MsgBox(ex.ToString)
End Try


End If

It seems like I am getting the HTML document just fine, is just that when I
try to use DrawToDC to get the application to print/send to the DC i Created
in memory, it causes the error.Any ideas on what I am doing wrong?

Here are the links to where I got the C# examples:
http://groups.google.com/groups?hl=.../groups?num=100&hl=en&lr=&q=DrawToDC++failure
http://blogs.msdn.com/rfarber/archive/2004/10/12/240943.aspx

thanks
 
C

Charles Law

Are you sure the error occurs on DrawToDc? I would expect an invalid cast
error on the line
render = bodyElement

I also assume that you have Option Strict Off. Turning it on will ensure you
cast objects correctly.

It looks to me like you are caught between two stools. On the one hand you
want a light-weight program without the rendering part of the WebBrowser or
InternetExplorer controls (ShdocVw), and on the other you want to render
elements using the IHTMLElementRender interface.

Unfortunately you can't use this interface unless you host mshtml properly,
and that includes the rendering part.

When you load the document below it is not rendered; just loaded into
memory. Therefore you cannot render it to a device context because there is
no rendered page to copy.

You can continue to manipulate the html as you have below, but if you want
to render it you must either use the WebBrowser/InternetExplorer controls or
host mshtml fully yourself.

HTH

Charles


ddd said:
Hi,

I am having problems with using the DrawToDC of the
MSHTML.iHTMLElementRender in a VB.net application. For some reason I am
getting a "catastrophic error". I am basing the code on c# examples, and I
am not sure what exactly I am doing wrong. From the C# posts it seems that
the drawtodc has a bug and you need to redifine it, so i followed their
advice and specified an interface as below:


Imports System
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports mshtml

<ComVisible(True), ComImport(),
Guid("3050f669-98b5-11cf-bb82-00aa00bdce0b"), _
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Interface IHTMLElementRender
Sub DrawToDC(<[In]()> ByVal hDC As IntPtr)
Sub SetDocumentPrinter(<[In](), MarshalAs(UnmanagedType.BStr)> ByVal
bstrPrinterName As String, <[In]()> ByVal hDC As IntPtr)
End Interface 'IHTMLElementRender

On the main form of the application I am doing the following:

Dim objMSHTML As HTMLDocument
Dim objDocument As IHTMLDocument2
Dim ips As IPersistStreamInit

objMSHTML = New HTMLDocument()

ips = DirectCast(objMSHTML, IPersistStreamInit)
ips.InitNew()

objDocument =
objMSHTML.createDocumentFromUrl("http://www.google.com", String.Empty)

Do Until objDocument.readyState = "complete"
Application.DoEvents()
Loop

MsgBox(objDocument.body.outerHTML)
Dim bodyElement As IHTMLElement
Dim render As IHTMLElementRender


If objDocument.body.outerHTML <> Nothing Then
bodyElement = objDocument.body
render = bodyElement
Dim img As New Bitmap(600, 400)
Dim g As Graphics = Graphics.FromImage(img)
Dim memDC As IntPtr
memDC = g.GetHdc()

Try
render.DrawToDC(memDC)
Catch ex As Exception
MsgBox(ex.ToString)
End Try


End If

It seems like I am getting the HTML document just fine, is just that when
I
try to use DrawToDC to get the application to print/send to the DC i
Created
in memory, it causes the error.Any ideas on what I am doing wrong?

Here are the links to where I got the C# examples:
http://groups.google.com/groups?hl=.../groups?num=100&hl=en&lr=&q=DrawToDC++failure
http://blogs.msdn.com/rfarber/archive/2004/10/12/240943.aspx

thanks
 
D

ddd

Hi Charles,

First of all thanks for taking the time to reply to this post. I am
definetly not getting an error on the render=bodyelement and i do have
Option Explicit On and Option Strict On for the IHTMLElementRender
interface class.

As about using the WebBrowser control. I am not sure how exactly to do this.
I added a reference to SHDocVw, but I still cannot figure out how to do this
properly. Do I just add the references, to I load the page through the
webbrowser object? I did look at the C# example and they declare an object
that as IHTMLDocument2 and than they set it to be the document of the
webbrowser, however, I got errors when I did this. I also was unclear if i
would need to load the URL through Navigate2 (of the webbrowser) or the
createDocumentFromUrl.

Can you point me to any documents/tutorial where they explain how to host
the MSHTML correctly?

thanks

tony

Charles Law said:
Are you sure the error occurs on DrawToDc? I would expect an invalid cast
error on the line
render = bodyElement

I also assume that you have Option Strict Off. Turning it on will ensure you
cast objects correctly.

It looks to me like you are caught between two stools. On the one hand you
want a light-weight program without the rendering part of the WebBrowser or
InternetExplorer controls (ShdocVw), and on the other you want to render
elements using the IHTMLElementRender interface.

Unfortunately you can't use this interface unless you host mshtml properly,
and that includes the rendering part.

When you load the document below it is not rendered; just loaded into
memory. Therefore you cannot render it to a device context because there is
no rendered page to copy.

You can continue to manipulate the html as you have below, but if you want
to render it you must either use the WebBrowser/InternetExplorer controls or
host mshtml fully yourself.

HTH

Charles


ddd said:
Hi,

I am having problems with using the DrawToDC of the
MSHTML.iHTMLElementRender in a VB.net application. For some reason I am
getting a "catastrophic error". I am basing the code on c# examples, and I
am not sure what exactly I am doing wrong. From the C# posts it seems that
the drawtodc has a bug and you need to redifine it, so i followed their
advice and specified an interface as below:


Imports System
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports mshtml

<ComVisible(True), ComImport(),
Guid("3050f669-98b5-11cf-bb82-00aa00bdce0b"), _
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Interface IHTMLElementRender
Sub DrawToDC(<[In]()> ByVal hDC As IntPtr)
Sub SetDocumentPrinter(<[In](), MarshalAs(UnmanagedType.BStr)> ByVal
bstrPrinterName As String, <[In]()> ByVal hDC As IntPtr)
End Interface 'IHTMLElementRender

On the main form of the application I am doing the following:

Dim objMSHTML As HTMLDocument
Dim objDocument As IHTMLDocument2
Dim ips As IPersistStreamInit

objMSHTML = New HTMLDocument()

ips = DirectCast(objMSHTML, IPersistStreamInit)
ips.InitNew()

objDocument =
objMSHTML.createDocumentFromUrl("http://www.google.com", String.Empty)

Do Until objDocument.readyState = "complete"
Application.DoEvents()
Loop

MsgBox(objDocument.body.outerHTML)
Dim bodyElement As IHTMLElement
Dim render As IHTMLElementRender


If objDocument.body.outerHTML <> Nothing Then
bodyElement = objDocument.body
render = bodyElement
Dim img As New Bitmap(600, 400)
Dim g As Graphics = Graphics.FromImage(img)
Dim memDC As IntPtr
memDC = g.GetHdc()

Try
render.DrawToDC(memDC)
Catch ex As Exception
MsgBox(ex.ToString)
End Try


End If

It seems like I am getting the HTML document just fine, is just that when
I
try to use DrawToDC to get the application to print/send to the DC i
Created
in memory, it causes the error.Any ideas on what I am doing wrong?

Here are the links to where I got the C# examples:
http://groups.google.com/groups?hl=.../groups?num=100&hl=en&lr=&q=DrawToDC++failure
http://blogs.msdn.com/rfarber/archive/2004/10/12/240943.aspx

thanks
 
D

ddd

I tried the following code which use the internetexplorer to load the page
and than use MSHTML, but this time I got a cast error at the
render=Bodyelement, didn't even make it to the DrawToDc.

Dim browser As New SHDocVw.InternetExplorer()

browser.Navigate("http://www.google.com")

Do Until browser.ReadyState = 4
Application.DoEvents()
Loop
Dim objDocument As IHTMLDocument2 = browser.Document

MsgBox(objDocument.body.outerHTML)

Dim bodyElement As IHTMLElement = objDocument.body

Dim render As IHTMLElementRender = bodyElement
Dim img As New Bitmap(600, 400)
Dim g As Graphics = Graphics.FromImage(img)
Dim memDC As IntPtr
memDC = g.GetHdc()

Try
render.DrawToDC(memDC)
Catch ex As Exception
MsgBox(ex.ToString)
End Try

I also tried to use the webbrowser and iWebBrowser2 like in the c# examples
but no luck in getting them work either. for some reason Navigate/Navigate2
were throwing uknown errors (i think because the control was not in the
form).

Any suggestions?


thanks

tony


Charles Law said:
Are you sure the error occurs on DrawToDc? I would expect an invalid cast
error on the line
render = bodyElement

I also assume that you have Option Strict Off. Turning it on will ensure you
cast objects correctly.

It looks to me like you are caught between two stools. On the one hand you
want a light-weight program without the rendering part of the WebBrowser or
InternetExplorer controls (ShdocVw), and on the other you want to render
elements using the IHTMLElementRender interface.

Unfortunately you can't use this interface unless you host mshtml properly,
and that includes the rendering part.

When you load the document below it is not rendered; just loaded into
memory. Therefore you cannot render it to a device context because there is
no rendered page to copy.

You can continue to manipulate the html as you have below, but if you want
to render it you must either use the WebBrowser/InternetExplorer controls or
host mshtml fully yourself.

HTH

Charles


ddd said:
Hi,

I am having problems with using the DrawToDC of the
MSHTML.iHTMLElementRender in a VB.net application. For some reason I am
getting a "catastrophic error". I am basing the code on c# examples, and I
am not sure what exactly I am doing wrong. From the C# posts it seems that
the drawtodc has a bug and you need to redifine it, so i followed their
advice and specified an interface as below:


Imports System
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports mshtml

<ComVisible(True), ComImport(),
Guid("3050f669-98b5-11cf-bb82-00aa00bdce0b"), _
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Interface IHTMLElementRender
Sub DrawToDC(<[In]()> ByVal hDC As IntPtr)
Sub SetDocumentPrinter(<[In](), MarshalAs(UnmanagedType.BStr)> ByVal
bstrPrinterName As String, <[In]()> ByVal hDC As IntPtr)
End Interface 'IHTMLElementRender

On the main form of the application I am doing the following:

Dim objMSHTML As HTMLDocument
Dim objDocument As IHTMLDocument2
Dim ips As IPersistStreamInit

objMSHTML = New HTMLDocument()

ips = DirectCast(objMSHTML, IPersistStreamInit)
ips.InitNew()

objDocument =
objMSHTML.createDocumentFromUrl("http://www.google.com", String.Empty)

Do Until objDocument.readyState = "complete"
Application.DoEvents()
Loop

MsgBox(objDocument.body.outerHTML)
Dim bodyElement As IHTMLElement
Dim render As IHTMLElementRender


If objDocument.body.outerHTML <> Nothing Then
bodyElement = objDocument.body
render = bodyElement
Dim img As New Bitmap(600, 400)
Dim g As Graphics = Graphics.FromImage(img)
Dim memDC As IntPtr
memDC = g.GetHdc()

Try
render.DrawToDC(memDC)
Catch ex As Exception
MsgBox(ex.ToString)
End Try


End If

It seems like I am getting the HTML document just fine, is just that when
I
try to use DrawToDC to get the application to print/send to the DC i
Created
in memory, it causes the error.Any ideas on what I am doing wrong?

Here are the links to where I got the C# examples:
http://groups.google.com/groups?hl=.../groups?num=100&hl=en&lr=&q=DrawToDC++failure
http://blogs.msdn.com/rfarber/archive/2004/10/12/240943.aspx

thanks
 
C

Charles Law

The easiest way in VB.NET is still to add a WebBrowser control to a form.
When I select Customize Toolbox, it shows up on the COM Components tab as
Microsoft Web Browser.

When you do this the WebBrowser control will be wrapped (it is an ActiveX)
and called AxWebBrowser1, indicating that it is wrapped in an AxHost. This
is to marshal calls backwards and forwards between managed and unmanaged
code.

The AxWebBrowser1 object will have a document property, which supports the
IHTMLDocument2 interface, amongst others.

If you do this you should find that you can cast bodyElement to render, as
in

render = DirectCast(bodyElement, mshtml.IHTMLElementRender)

Just a note on the Option Strict thing: when you say that you have it on, do
you mean that you have a statement

Option Strict On

at the start of the module containing the code? If so, I would expect a
compile error on the line

render = bodyElement

because they are not the same types.

HTH

Charles


ddd said:
Hi Charles,

First of all thanks for taking the time to reply to this post. I am
definetly not getting an error on the render=bodyelement and i do have
Option Explicit On and Option Strict On for the IHTMLElementRender
interface class.

As about using the WebBrowser control. I am not sure how exactly to do
this.
I added a reference to SHDocVw, but I still cannot figure out how to do
this
properly. Do I just add the references, to I load the page through the
webbrowser object? I did look at the C# example and they declare an object
that as IHTMLDocument2 and than they set it to be the document of the
webbrowser, however, I got errors when I did this. I also was unclear if i
would need to load the URL through Navigate2 (of the webbrowser) or the
createDocumentFromUrl.

Can you point me to any documents/tutorial where they explain how to host
the MSHTML correctly?

thanks

tony

Charles Law said:
Are you sure the error occurs on DrawToDc? I would expect an invalid cast
error on the line
render = bodyElement

I also assume that you have Option Strict Off. Turning it on will ensure you
cast objects correctly.

It looks to me like you are caught between two stools. On the one hand
you
want a light-weight program without the rendering part of the WebBrowser or
InternetExplorer controls (ShdocVw), and on the other you want to render
elements using the IHTMLElementRender interface.

Unfortunately you can't use this interface unless you host mshtml properly,
and that includes the rendering part.

When you load the document below it is not rendered; just loaded into
memory. Therefore you cannot render it to a device context because there is
no rendered page to copy.

You can continue to manipulate the html as you have below, but if you
want
to render it you must either use the WebBrowser/InternetExplorer controls or
host mshtml fully yourself.

HTH

Charles


ddd said:
Hi,

I am having problems with using the DrawToDC of the
MSHTML.iHTMLElementRender in a VB.net application. For some reason I am
getting a "catastrophic error". I am basing the code on c# examples,
and I
am not sure what exactly I am doing wrong. From the C# posts it seems that
the drawtodc has a bug and you need to redifine it, so i followed their
advice and specified an interface as below:


Imports System
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports mshtml

<ComVisible(True), ComImport(),
Guid("3050f669-98b5-11cf-bb82-00aa00bdce0b"), _
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Interface IHTMLElementRender
Sub DrawToDC(<[In]()> ByVal hDC As IntPtr)
Sub SetDocumentPrinter(<[In](), MarshalAs(UnmanagedType.BStr)> ByVal
bstrPrinterName As String, <[In]()> ByVal hDC As IntPtr)
End Interface 'IHTMLElementRender

On the main form of the application I am doing the following:

Dim objMSHTML As HTMLDocument
Dim objDocument As IHTMLDocument2
Dim ips As IPersistStreamInit

objMSHTML = New HTMLDocument()

ips = DirectCast(objMSHTML, IPersistStreamInit)
ips.InitNew()

objDocument =
objMSHTML.createDocumentFromUrl("http://www.google.com", String.Empty)

Do Until objDocument.readyState = "complete"
Application.DoEvents()
Loop

MsgBox(objDocument.body.outerHTML)
Dim bodyElement As IHTMLElement
Dim render As IHTMLElementRender


If objDocument.body.outerHTML <> Nothing Then
bodyElement = objDocument.body
render = bodyElement
Dim img As New Bitmap(600, 400)
Dim g As Graphics = Graphics.FromImage(img)
Dim memDC As IntPtr
memDC = g.GetHdc()

Try
render.DrawToDC(memDC)
Catch ex As Exception
MsgBox(ex.ToString)
End Try


End If

It seems like I am getting the HTML document just fine, is just that when
I
try to use DrawToDC to get the application to print/send to the DC i
Created
in memory, it causes the error.Any ideas on what I am doing wrong?

Here are the links to where I got the C# examples:
http://groups.google.com/groups?hl=.../groups?num=100&hl=en&lr=&q=DrawToDC++failure
http://blogs.msdn.com/rfarber/archive/2004/10/12/240943.aspx

thanks
 
C

Charles Law

You are right about the unknown errors (unspecified error, I think). This
is, as you surmise, because mshtml is not hosted properly. As per my other
reply, the easiest way to is to put a WebBrowser control on the form. I
wouldn't recommend going the other route (hosting it manually) as all you
will end up doing is recreating the code already in the WebBrowser control,
and it is not for the faint-hearted.

Charles


ddd said:
I tried the following code which use the internetexplorer to load the page
and than use MSHTML, but this time I got a cast error at the
render=Bodyelement, didn't even make it to the DrawToDc.

Dim browser As New SHDocVw.InternetExplorer()

browser.Navigate("http://www.google.com")

Do Until browser.ReadyState = 4
Application.DoEvents()
Loop
Dim objDocument As IHTMLDocument2 = browser.Document

MsgBox(objDocument.body.outerHTML)

Dim bodyElement As IHTMLElement = objDocument.body

Dim render As IHTMLElementRender = bodyElement
Dim img As New Bitmap(600, 400)
Dim g As Graphics = Graphics.FromImage(img)
Dim memDC As IntPtr
memDC = g.GetHdc()

Try
render.DrawToDC(memDC)
Catch ex As Exception
MsgBox(ex.ToString)
End Try

I also tried to use the webbrowser and iWebBrowser2 like in the c#
examples
but no luck in getting them work either. for some reason
Navigate/Navigate2
were throwing uknown errors (i think because the control was not in the
form).

Any suggestions?


thanks

tony


Charles Law said:
Are you sure the error occurs on DrawToDc? I would expect an invalid cast
error on the line
render = bodyElement

I also assume that you have Option Strict Off. Turning it on will ensure you
cast objects correctly.

It looks to me like you are caught between two stools. On the one hand
you
want a light-weight program without the rendering part of the WebBrowser or
InternetExplorer controls (ShdocVw), and on the other you want to render
elements using the IHTMLElementRender interface.

Unfortunately you can't use this interface unless you host mshtml properly,
and that includes the rendering part.

When you load the document below it is not rendered; just loaded into
memory. Therefore you cannot render it to a device context because there is
no rendered page to copy.

You can continue to manipulate the html as you have below, but if you
want
to render it you must either use the WebBrowser/InternetExplorer controls or
host mshtml fully yourself.

HTH

Charles


ddd said:
Hi,

I am having problems with using the DrawToDC of the
MSHTML.iHTMLElementRender in a VB.net application. For some reason I am
getting a "catastrophic error". I am basing the code on c# examples,
and I
am not sure what exactly I am doing wrong. From the C# posts it seems that
the drawtodc has a bug and you need to redifine it, so i followed their
advice and specified an interface as below:


Imports System
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports mshtml

<ComVisible(True), ComImport(),
Guid("3050f669-98b5-11cf-bb82-00aa00bdce0b"), _
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Interface IHTMLElementRender
Sub DrawToDC(<[In]()> ByVal hDC As IntPtr)
Sub SetDocumentPrinter(<[In](), MarshalAs(UnmanagedType.BStr)> ByVal
bstrPrinterName As String, <[In]()> ByVal hDC As IntPtr)
End Interface 'IHTMLElementRender

On the main form of the application I am doing the following:

Dim objMSHTML As HTMLDocument
Dim objDocument As IHTMLDocument2
Dim ips As IPersistStreamInit

objMSHTML = New HTMLDocument()

ips = DirectCast(objMSHTML, IPersistStreamInit)
ips.InitNew()

objDocument =
objMSHTML.createDocumentFromUrl("http://www.google.com", String.Empty)

Do Until objDocument.readyState = "complete"
Application.DoEvents()
Loop

MsgBox(objDocument.body.outerHTML)
Dim bodyElement As IHTMLElement
Dim render As IHTMLElementRender


If objDocument.body.outerHTML <> Nothing Then
bodyElement = objDocument.body
render = bodyElement
Dim img As New Bitmap(600, 400)
Dim g As Graphics = Graphics.FromImage(img)
Dim memDC As IntPtr
memDC = g.GetHdc()

Try
render.DrawToDC(memDC)
Catch ex As Exception
MsgBox(ex.ToString)
End Try


End If

It seems like I am getting the HTML document just fine, is just that when
I
try to use DrawToDC to get the application to print/send to the DC i
Created
in memory, it causes the error.Any ideas on what I am doing wrong?

Here are the links to where I got the C# examples:
http://groups.google.com/groups?hl=.../groups?num=100&hl=en&lr=&q=DrawToDC++failure
http://blogs.msdn.com/rfarber/archive/2004/10/12/240943.aspx

thanks
 
D

ddd

Charles,

Thanks for your help on this. I got it working with the WebControl embeded
on the form, however, the problem is that the control has to be visible and
the snapshot displays only the part of the control that is being rendered on
the form.

Any ideas on how I could make this work without having to display the web
control? I tried to change the visibility of the control but no luck.

The code I have right now is:

On Main form (web is the webbrowser control):
web.Navigate("http://www.google.com")

Do Until web.ReadyState = 4

Application.DoEvents()

Loop

Dim objDocument As IHTMLDocument2 = web.Document

Dim bodyElement As IHTMLElement = objDocument.body

Dim bmp As Bitmap

bmp = snapshot.CreateBitmap(bodyElement)



bmp.Save("c:\testingsnap.bmp")

on the snapshot class:

Public Shared Function CreateBitmap( _

ByVal element As IHTMLElement) As Bitmap

Dim render As IHTMLElementRender

render = DirectCast(element, mshtml.IHTMLElementRender)

Dim gDest As Graphics

Dim memDC As IntPtr

CreateBitmap = New Bitmap(600, 400)

gDest = gDest.FromImage(CreateBitmap)

memDC = gDest.GetHdc

Try

render.DrawToDC(memDC)

MsgBox("drawtodc worked")

Catch ex As Exception

MsgBox(ex.ToString)

End Try

gDest.ReleaseHdc(memDC)

End Function

thanks

tony

Charles Law said:
You are right about the unknown errors (unspecified error, I think). This
is, as you surmise, because mshtml is not hosted properly. As per my other
reply, the easiest way to is to put a WebBrowser control on the form. I
wouldn't recommend going the other route (hosting it manually) as all you
will end up doing is recreating the code already in the WebBrowser control,
and it is not for the faint-hearted.

Charles


ddd said:
I tried the following code which use the internetexplorer to load the page
and than use MSHTML, but this time I got a cast error at the
render=Bodyelement, didn't even make it to the DrawToDc.

Dim browser As New SHDocVw.InternetExplorer()

browser.Navigate("http://www.google.com")

Do Until browser.ReadyState = 4
Application.DoEvents()
Loop
Dim objDocument As IHTMLDocument2 = browser.Document

MsgBox(objDocument.body.outerHTML)

Dim bodyElement As IHTMLElement = objDocument.body

Dim render As IHTMLElementRender = bodyElement
Dim img As New Bitmap(600, 400)
Dim g As Graphics = Graphics.FromImage(img)
Dim memDC As IntPtr
memDC = g.GetHdc()

Try
render.DrawToDC(memDC)
Catch ex As Exception
MsgBox(ex.ToString)
End Try

I also tried to use the webbrowser and iWebBrowser2 like in the c#
examples
but no luck in getting them work either. for some reason
Navigate/Navigate2
were throwing uknown errors (i think because the control was not in the
form).

Any suggestions?


thanks

tony


Charles Law said:
Are you sure the error occurs on DrawToDc? I would expect an invalid cast
error on the line

render = bodyElement

I also assume that you have Option Strict Off. Turning it on will
ensure
you
cast objects correctly.

It looks to me like you are caught between two stools. On the one hand
you
want a light-weight program without the rendering part of the
WebBrowser
or
InternetExplorer controls (ShdocVw), and on the other you want to render
elements using the IHTMLElementRender interface.

Unfortunately you can't use this interface unless you host mshtml properly,
and that includes the rendering part.

When you load the document below it is not rendered; just loaded into
memory. Therefore you cannot render it to a device context because
there
is
no rendered page to copy.

You can continue to manipulate the html as you have below, but if you
want
to render it you must either use the WebBrowser/InternetExplorer
controls
or
host mshtml fully yourself.

HTH

Charles


Hi,

I am having problems with using the DrawToDC of the
MSHTML.iHTMLElementRender in a VB.net application. For some reason I am
getting a "catastrophic error". I am basing the code on c# examples,
and I
am not sure what exactly I am doing wrong. From the C# posts it seems that
the drawtodc has a bug and you need to redifine it, so i followed their
advice and specified an interface as below:


Imports System
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports mshtml

<ComVisible(True), ComImport(),
Guid("3050f669-98b5-11cf-bb82-00aa00bdce0b"), _
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Interface IHTMLElementRender
Sub DrawToDC(<[In]()> ByVal hDC As IntPtr)
Sub SetDocumentPrinter(<[In](), MarshalAs(UnmanagedType.BStr)> ByVal
bstrPrinterName As String, <[In]()> ByVal hDC As IntPtr)
End Interface 'IHTMLElementRender

On the main form of the application I am doing the following:

Dim objMSHTML As HTMLDocument
Dim objDocument As IHTMLDocument2
Dim ips As IPersistStreamInit

objMSHTML = New HTMLDocument()

ips = DirectCast(objMSHTML, IPersistStreamInit)
ips.InitNew()

objDocument =
objMSHTML.createDocumentFromUrl("http://www.google.com", String.Empty)

Do Until objDocument.readyState = "complete"
Application.DoEvents()
Loop

MsgBox(objDocument.body.outerHTML)
Dim bodyElement As IHTMLElement
Dim render As IHTMLElementRender


If objDocument.body.outerHTML <> Nothing Then
bodyElement = objDocument.body
render = bodyElement
Dim img As New Bitmap(600, 400)
Dim g As Graphics = Graphics.FromImage(img)
Dim memDC As IntPtr
memDC = g.GetHdc()

Try
render.DrawToDC(memDC)
Catch ex As Exception
MsgBox(ex.ToString)
End Try


End If

It seems like I am getting the HTML document just fine, is just that when
I
try to use DrawToDC to get the application to print/send to the DC i
Created
in memory, it causes the error.Any ideas on what I am doing wrong?

Here are the links to where I got the C# examples:
http://groups.google.com/groups?hl=.../groups?num=100&hl=en&lr=&q=DrawToDC++failure
 
C

Charles Law

Tony, sorry for the delay. I see you posted this some time ago, so perhaps
you have found a solution. For some reason that I am so far unable to
explain, OE or the Microsoft server does not always send me every message
posted, and this one has just appeared.

Anyway, the simple answer is that I don't know a way to do it without the
browser being visible. However, it makes sense to me that it must be visible
because it is only then that it would render the content.

Good luck.

Charles


ddd said:
Charles,

Thanks for your help on this. I got it working with the WebControl embeded
on the form, however, the problem is that the control has to be visible
and
the snapshot displays only the part of the control that is being rendered
on
the form.

Any ideas on how I could make this work without having to display the web
control? I tried to change the visibility of the control but no luck.

The code I have right now is:

On Main form (web is the webbrowser control):
web.Navigate("http://www.google.com")

Do Until web.ReadyState = 4

Application.DoEvents()

Loop

Dim objDocument As IHTMLDocument2 = web.Document

Dim bodyElement As IHTMLElement = objDocument.body

Dim bmp As Bitmap

bmp = snapshot.CreateBitmap(bodyElement)



bmp.Save("c:\testingsnap.bmp")

on the snapshot class:

Public Shared Function CreateBitmap( _

ByVal element As IHTMLElement) As Bitmap

Dim render As IHTMLElementRender

render = DirectCast(element, mshtml.IHTMLElementRender)

Dim gDest As Graphics

Dim memDC As IntPtr

CreateBitmap = New Bitmap(600, 400)

gDest = gDest.FromImage(CreateBitmap)

memDC = gDest.GetHdc

Try

render.DrawToDC(memDC)

MsgBox("drawtodc worked")

Catch ex As Exception

MsgBox(ex.ToString)

End Try

gDest.ReleaseHdc(memDC)

End Function

thanks

tony

Charles Law said:
You are right about the unknown errors (unspecified error, I think). This
is, as you surmise, because mshtml is not hosted properly. As per my
other
reply, the easiest way to is to put a WebBrowser control on the form. I
wouldn't recommend going the other route (hosting it manually) as all you
will end up doing is recreating the code already in the WebBrowser control,
and it is not for the faint-hearted.

Charles


ddd said:
I tried the following code which use the internetexplorer to load the page
and than use MSHTML, but this time I got a cast error at the
render=Bodyelement, didn't even make it to the DrawToDc.

Dim browser As New SHDocVw.InternetExplorer()

browser.Navigate("http://www.google.com")

Do Until browser.ReadyState = 4
Application.DoEvents()
Loop
Dim objDocument As IHTMLDocument2 = browser.Document

MsgBox(objDocument.body.outerHTML)

Dim bodyElement As IHTMLElement = objDocument.body

Dim render As IHTMLElementRender = bodyElement
Dim img As New Bitmap(600, 400)
Dim g As Graphics = Graphics.FromImage(img)
Dim memDC As IntPtr
memDC = g.GetHdc()

Try
render.DrawToDC(memDC)
Catch ex As Exception
MsgBox(ex.ToString)
End Try

I also tried to use the webbrowser and iWebBrowser2 like in the c#
examples
but no luck in getting them work either. for some reason
Navigate/Navigate2
were throwing uknown errors (i think because the control was not in the
form).

Any suggestions?


thanks

tony


Are you sure the error occurs on DrawToDc? I would expect an invalid cast
error on the line

render = bodyElement

I also assume that you have Option Strict Off. Turning it on will ensure
you
cast objects correctly.

It looks to me like you are caught between two stools. On the one hand
you
want a light-weight program without the rendering part of the WebBrowser
or
InternetExplorer controls (ShdocVw), and on the other you want to render
elements using the IHTMLElementRender interface.

Unfortunately you can't use this interface unless you host mshtml
properly,
and that includes the rendering part.

When you load the document below it is not rendered; just loaded into
memory. Therefore you cannot render it to a device context because there
is
no rendered page to copy.

You can continue to manipulate the html as you have below, but if you
want
to render it you must either use the WebBrowser/InternetExplorer controls
or
host mshtml fully yourself.

HTH

Charles


Hi,

I am having problems with using the DrawToDC of the
MSHTML.iHTMLElementRender in a VB.net application. For some reason I am
getting a "catastrophic error". I am basing the code on c# examples,
and
I
am not sure what exactly I am doing wrong. From the C# posts it
seems
that
the drawtodc has a bug and you need to redifine it, so i followed their
advice and specified an interface as below:


Imports System
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports mshtml

<ComVisible(True), ComImport(),
Guid("3050f669-98b5-11cf-bb82-00aa00bdce0b"), _
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Interface IHTMLElementRender
Sub DrawToDC(<[In]()> ByVal hDC As IntPtr)
Sub SetDocumentPrinter(<[In](), MarshalAs(UnmanagedType.BStr)> ByVal
bstrPrinterName As String, <[In]()> ByVal hDC As IntPtr)
End Interface 'IHTMLElementRender

On the main form of the application I am doing the following:

Dim objMSHTML As HTMLDocument
Dim objDocument As IHTMLDocument2
Dim ips As IPersistStreamInit

objMSHTML = New HTMLDocument()

ips = DirectCast(objMSHTML, IPersistStreamInit)
ips.InitNew()

objDocument =
objMSHTML.createDocumentFromUrl("http://www.google.com", String.Empty)

Do Until objDocument.readyState = "complete"
Application.DoEvents()
Loop

MsgBox(objDocument.body.outerHTML)
Dim bodyElement As IHTMLElement
Dim render As IHTMLElementRender


If objDocument.body.outerHTML <> Nothing Then
bodyElement = objDocument.body
render = bodyElement
Dim img As New Bitmap(600, 400)
Dim g As Graphics = Graphics.FromImage(img)
Dim memDC As IntPtr
memDC = g.GetHdc()

Try
render.DrawToDC(memDC)
Catch ex As Exception
MsgBox(ex.ToString)
End Try


End If

It seems like I am getting the HTML document just fine, is just that
when
I
try to use DrawToDC to get the application to print/send to the DC i
Created
in memory, it causes the error.Any ideas on what I am doing wrong?

Here are the links to where I got the C# examples:

http://groups.google.com/groups?hl=.../groups?num=100&hl=en&lr=&q=DrawToDC++failure
http://blogs.msdn.com/rfarber/archive/2004/10/12/240943.aspx

thanks
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top