Re: UCOMIStream, MSHTML and WebBrowser control Persistence Problem
From: Charles Law (blank_at_nowhere.com)
Date: 03/16/04
- Next message: Michael Tissington: "Quit event not fireing"
- Previous message: Richard Bell: "Silent IE SAVEAS"
- In reply to: Ken Hanson: "Re: UCOMIStream, MSHTML and WebBrowser control Persistence Problem"
- Next in thread: Ken Hanson: "Re: UCOMIStream, MSHTML and WebBrowser control Persistence Problem"
- Reply: Ken Hanson: "Re: UCOMIStream, MSHTML and WebBrowser control Persistence Problem"
- Messages sorted by: [ date ] [ thread ]
Date: Tue, 16 Mar 2004 23:40:53 -0000
Ken
Although probably not the problem, it looks like you might be caching the
document object. It is best to retrieve it from the control each time you
need a reference.
When you talk about 'dialog form unload', do you mean that you close the
form that hosts the browser control and then re-open it? The browser control
needs to be disposed explicitly, so you should have a call to Dispose when
you close the form.
You say that objects are not available on subsequent occasions. Do you get
an error? When you load the form, I do not see a Navigate("about:blank").
This is required to initialise the control before you do anything else, and
then you must wait for DocumentComplete (readyState = "complete") before you
continue.
HTH
Charles
"Ken Hanson" <khanson@capstonetechnology.com> wrote in message
news:eTyO2t6CEHA.2800@tk2msftngp13.phx.gbl...
> 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: Michael Tissington: "Quit event not fireing"
- Previous message: Richard Bell: "Silent IE SAVEAS"
- In reply to: Ken Hanson: "Re: UCOMIStream, MSHTML and WebBrowser control Persistence Problem"
- Next in thread: Ken Hanson: "Re: UCOMIStream, MSHTML and WebBrowser control Persistence Problem"
- Reply: Ken Hanson: "Re: UCOMIStream, MSHTML and WebBrowser control Persistence Problem"
- Messages sorted by: [ date ] [ thread ]
Relevant Pages
|
|