Re: UCOMIStream, MSHTML and WebBrowser control Persistence Problem
From: Ken Hanson (khanson_at_capstonetechnology.com)
Date: 03/16/04
- Next message: Craig Buchanan: "Re: DataAccess Block issue"
- Previous message: David Browne: "Re: DataAccess Block issue"
- In reply to: Charles Law: "Re: UCOMIStream, MSHTML and WebBrowser control Persistence Problem"
- Next in thread: Charles Law: "Re: UCOMIStream, MSHTML and WebBrowser control Persistence Problem"
- Reply: Charles Law: "Re: UCOMIStream, MSHTML and WebBrowser control Persistence Problem"
- Messages sorted by: [ date ] [ thread ]
Date: Tue, 16 Mar 2004 15:07:28 -0800
Charles,
Thanks for the advice. Per your suggestion I moved the load from stream
logic to the form load event and it worked great. After looking a little
closer I saw that the C++ example that Microsoft shows avoids the infite
event firing loop by checking the interface pointer of the document to make
sure it is the one you want, this is difficult to do in .NET and not worth
the effort since it works as seen below.
Unfortantely I Now I have a new problem. It appears that I can only load
once from the stream. If I let the dialog form unload and release object
accordingly a second attempt at loading the document seems to succeed but
objects in the document are not available as they were the first time.
Are you familiar with any thing I need to explicity clean up to avoid
confusing COM/WebBrowser interface?
Thanks much for your help.
- Ken
In Form load:
objDocument = WebBrowser1.Document
strHTML = objSR.ReadToEnd()
hGlobal = Marshal.StringToHGlobalAnsi(strHTML)
CreateStreamOnHGlobal(hGlobal, True, strm)
objPersistStreamInit = DirectCast(objDocument, IPersistStreamInit)
objPersistStreamInit.InitNew()
objPersistStreamInit.Load(strm)
Do While WebBrowser1.ReadyState <> tagREADYSTATE.READYSTATE_COMPLETE
Application.DoEvents()
Loop
objDocument = WebBrowser1.Document
...
Subsequent call to vbscript function in document, works once, does not work
on subsequent doucment loads?
Call objDocument.Script.PopupDrawXYPlot(strXMLData, lngCurveFitStyles)
"Charles Law" <blank@nowhere.com> wrote in message
news:OWLSze6CEHA.2628@TK2MSFTNGP11.phx.gbl...
> Hi Ken
>
> It looks to me that your technique is correct. The problem, I suspect, is
> where you load the document from the stream. Since documents are loaded
> asynchronously, the logic of the load process is
>
> 1. Put html into stream
> 2. Load document from stream
> 3. Wait for operation to complete
> 4. Continue ...
>
> Step 3 means waiting for the readyState to become 'complete', and when
that
> happens the DocumentComplete event fires. As you are loading the document
in
> the DocumentComplete event, you will get into a continuous loop.
>
> I would suggest that you either load the document outside the
> DocumentComplete event (preferred), or set a flag in the event, before you
> load, to say that you are currently loading. This way you can avoid
> reloading the document.
>
> The preferred way would be to wait for the browser initialisation to
> complete (that is, it finishes navigating to about:blank, which you must
> instruct it to do), and then load the document, waiting for readyState
> before continuing
>
> HTH
>
> Charles
>
>
> "Ken Hanson" <khanson@capstonetechnology.com> wrote in message
> news:%23cYb7l4CEHA.1604@TK2MSFTNGP11.phx.gbl...
> > Charels,
> >
> > I have seen several threads where it appears you have been sucesfull
> loading
> > the WebBrowser control from a stream in the DocumentComplete event from
> > vb.net. I have been struggeling with this myself and was hoping you
might
> > illuminate me.
> >
> > Bottom line is that when I try to load from a stream, no error is thrown
> but
> > I seem to go into a infinite event loop where DocumentComplete keeps
being
> > fired.
> >
> > Any help would be appreciated.
> >
> > Thanks,
> >
> > Ken
> >
> > Here are the bits that appear to be important:
> >
> > Dim TrendHTML As Stream =
> >
>
System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(
> > "CTCTrend.TrendGraphics.htm")
> >
> > ...
> >
> > Private Sub WebBrowser1_DocumentComplete(ByVal eventSender As
> System.Object,
> > ByVal eventArgs As AxSHDocVw.DWebBrowserEvents2_DocumentCompleteEvent)
> > Handles WebBrowser1.DocumentComplete
> >
> > Dim bResult As Boolean
> >
> > Dim strm As UCOMIStream
> >
> > Dim objPersistStreamInit As IPersistStreamInit
> >
> > Dim hGlobal As IntPtr
> >
> > Dim strHTML As String
> >
> > Dim objSR As New StreamReader(TrendHTML)
> >
> > Try
> >
> > objDocument = WebBrowser1.Document
> >
> > strHTML = objSR.ReadToEnd() 'objSR is a stream reader initialized
durring
> > form load
> >
> > hGlobal = Marshal.StringToHGlobalAnsi(strHTML)
> >
> > CreateStreamOnHGlobal(hGlobal, True, strm)
> >
> > objPersistStreamInit = DirectCast(objDocument, IPersistStreamInit)
> >
> > objPersistStreamInit.InitNew()
> >
> > objPersistStreamInit.Load(strm)
> >
> > Catch ex As Exception
> >
> > msgbox ex.Mesage
> >
> > End Try
> >
> > End Sub
> >
> > "Charles Law" <blank@nowhere.com> wrote in message
> > news:efMqFaW%23DHA.3812@TK2MSFTNGP09.phx.gbl...
> > > Sorry for the cross post, but I'm not sure who is best placed to
answer
> > this
> > > one.
> > >
> > > This is the most bizarre behaviour of MSHTML and streams.
> > >
> > > I have a WebBrowser control that contains nothing but some default
HTML.
> I
> > > want to copy the document and modify it before saving it to disk.
> > >
> > > So, I clone the document like this:
> > >
> > > <code>
> > > Private Function CloneDocument(ByVal doc As mshtml.IHTMLDocument2)
> As
> > > mshtml.IHTMLDocument2
> > >
> > > Dim newdoc2 As mshtml.IHTMLDocument2
> > > Dim ips As IPersistStreamInit
> > >
> > > Dim strm As UCOMIStream
> > >
> > > Dim source As String
> > >
> > > ' Create and initialise a new document object
> > > newdoc2 = New mshtml.HTMLDocument
> > >
> > > ips = DirectCast(newdoc2, IPersistStreamInit)
> > >
> > > ips.InitNew()
> > >
> > > Do Until newdoc2.readyState = "complete"
> > > Application.DoEvents()
> > > Loop
> > >
> > > ' Get the current document HTML as a stream
> > > source = GetDocumentSource(AxWebBrowser1.Document) ' see below
> > > strm = GetStream(source) ' see below
> > >
> > > ' Load the new document from the stream
> > > ips.Load(strm)
> > >
> > > ' Wait until the new document has settled
> > > Do Until newdoc2.readyState = "complete"
> > > Application.DoEvents()
> > > Loop
> > >
> > > Return newdoc2
> > >
> > > End Function
> > >
> > > Private Function GetStream(ByVal s As String) As UCOMIStream
> > >
> > > Dim iptr As IntPtr
> > > Dim istrm As UCOMIStream
> > >
> > > ' Get a pointer to the string
> > > iptr = Marshal.StringToHGlobalAuto(s)
> > >
> > > ' Create the stream from the pointer
> > > CreateStreamOnHGlobal(iptr, True, istrm)
> > >
> > > Return istrm
> > >
> > > End Function
> > > Private Function GetStream(ByVal size As Integer) As UCOMIStream
> > >
> > > Dim iptr As IntPtr
> > > Dim strm As UCOMIStream
> > >
> > > ' Create a pointer to a block of the required size
> > > iptr = Marshal.AllocHGlobal(size)
> > >
> > > ' Create the stream from the pointer
> > > CreateStreamOnHGlobal(iptr, True, strm)
> > >
> > > Return strm
> > >
> > > End Function
> > >
> > > Private Function GetDocumentSource(ByVal doc As
> mshtml.IHTMLDocument2,
> > > ByVal resetIsDirty As Boolean) As String
> > >
> > > Dim stream As UCOMIStream
> > >
> > > Dim ips As IPersistStreamInit
> > >
> > > Dim s As String
> > >
> > > ips = DirectCast(doc, IPersistStreamInit)
> > >
> > > If ips Is Nothing Then
> > > s = Nothing
> > > Else
> > > stream = GetStream(2048)
> > >
> > > ' Save the document into the comstream, without clearing
the
> > > IsDirty flag
> > > ips.Save(stream, resetIsDirty)
> > >
> > > s = StreamToString(stream)
> > > End If
> > >
> > > Return s
> > >
> > > End Function
> > >
> > > Private Function StreamToString(ByVal strm As UCOMIStream) As
String
> > >
> > > Dim iptr As IntPtr
> > >
> > > Dim s As String
> > >
> > > GetHGlobalFromStream(strm, iptr)
> > >
> > > ' *** THIS IS ODD TOO ***
> > > ' If the source is the WebBrowser control then Ansi must be
used
> > ***
> > > s = Marshal.PtrToStringAnsi(iptr)
> > >
> > > ' If the source is the cloned and modified document then Auto
> must
> > > be used ***
> > > s = Marshal.PtrToStringAuto(iptr)
> > >
> > > ' ***
> > >
> > > Return s
> > >
> > > End Function
> > > </code>
> > >
> > > Having cloned the document, I modify it by inserting some tags into
the
> > body
> > > element. I then call GetDocumentSource() to get the HTML from the
cloned
> > > document.
> > >
> > > However, the HTML that is returned is the original HTML, from the
> > WebBrowser
> > > control, and not from the cloned document. I know that the cloned
> document
> > > contains the correct HTML because if I execute the following for the
> > cloned
> > > document
> > >
> > > ?doc.all.tags("html").Item(0).outerhtml
> > >
> > > in the command window, I get what I expect in the body element.
> > >
> > > Can anyone suggest why this is happening?
> > >
> > > I have also highlighted an oddity in function StreamToString(), which
I
> do
> > > not understand. Why would the encoding of the HTML change between the
> > > browser and a cloned document?
> > >
> > > TIA
> > >
> > > Charles
> > >
> > >
> >
> >
>
>
- Next message: Craig Buchanan: "Re: DataAccess Block issue"
- Previous message: David Browne: "Re: DataAccess Block issue"
- In reply to: Charles Law: "Re: UCOMIStream, MSHTML and WebBrowser control Persistence Problem"
- Next in thread: Charles Law: "Re: UCOMIStream, MSHTML and WebBrowser control Persistence Problem"
- Reply: Charles Law: "Re: UCOMIStream, MSHTML and WebBrowser control Persistence Problem"
- Messages sorted by: [ date ] [ thread ]
Relevant Pages
|