This article illustrates how to use the IPersistStreamInit interface and its associated methods, and describes the steps required to load a page from a stream using the Web browser object and Microsoft® Visual C++® .
This article is divided into the following sections:
The IWebBrowser2::Navigate2 method of the IWebBrowser2 interface allows you to navigate the browser to any URL that is valid. In the following sample code, the IWebBrowser2::Navigate2 method is used to navigate the browser to the about:blank page. This page was selected because it is a valid URL, and it has the beneficial side effect of loading Mshtml.dll, so that you can obtain a pointer to the document object.
m_spWebBrowser->Navigate2(_T("about:blank"),NULL,NULL);
The Object Model is used to access and manipulate the contents of an HTML page. However, this pointer is valid only after the loading of the page is successfully completed.
Since the page needs to be fully and successfully loaded prior to accessing the document pointer, you should access the document pointer in your event handler for the DocumentComplete event of the WebBrowser control. This event is fired once for each frame in the page, and once when the top frame of the document is fully loaded. You can distinguish the DocumentComplete event for the top frame from others by comparing the parameter passed to the Web browser's IDispatch pointer.
void myObject::DocumentComplete(LPDISPATCH pDisp, VARIANT* URL) { HRESULT hr; LPUNKNOWN pUnkContainedBrowser = NULL; LPUNKNOWN pUnkDispParam = NULL; IStream *pStream = NULL; HGLOBAL hHTMLText; CHAR szHTMLText[] = "<html><h1>Stream Test</h1><p>This HTML content is being loaded from a stream.</html>"; // Test for valid pointers. // if (!m_pBrowserApp || !pDisp) goto Cleanup; // To test object equality, use COM identity rules: query both // pointers for IUnknown and compare them. // hr = m_pBrowserApp->QueryInterface(IID_IUnknown, (void**)&pUnkContainedBrowser); if (hr) goto Cleanup; // Query the passed-in IDispatch for IUnknown. // hr = pDisp->QueryInterface(IID_IUnknown, (void**)&pUnkDispParam); if (hr) goto Cleanup; // If they're unequal, the event is for a subframe and we're not // interested. // if (pUnkContainedBrowser != pUnkDispParam) goto Cleanup; // As a further check, make sure the URL is "about:blank". // if (URL && V_VT(URL) == VT_BSTR && StrCmpIW(URL->bstrVal, L"about:blank") != 0) goto Cleanup; hHTMLText = GlobalAlloc(GPTR, lstrlen(szHTMLText)+1); if (!hHTMLText) goto Cleanup; lstrcpy((CHAR *)hHTMLText, szHTMLText); hr = CreateStreamOnHGlobal(hHTMLText, TRUE, &pStream); if (hr) goto Cleanup; // Call the helper function to load the WebOC from the stream. // hr = LoadWebOCFromStream(m_pBrowserApp, pStream); Cleanup: if (pStream) pStream->Release(); if (pUnkContainedBrowser) pUnkContainedBrowser->Release(); if (pUnkDispParam) pUnkDispParam->Release(); }
Given the m_spWebBrowser pointer, you can perform a QueryInterface operation on any object for IID_IPersistStreamInit to obtain the IPersistStreamInit pointer, as shown in the following code:
// // Function: LoadWebOCFromStream // // Description: Takes an IWebBrowser pointer and causes the stream to // be loaded into the contained HTML Document Object. // HRESULT LoadWebOCFromStream(IWebBrowser *pWebBrowser, IStream *pStream) { HRESULT hr; LPDISPATCH pHtmlDoc = NULL; IPersistStreamInit *pPersistStreamInit = NULL; // Test for valid pointers. // if (!pWebBrowser || !pStream) return E_POINTER; // Get to the document object's IDispatch pointer. // hr = pWebBrowser->get_Document(&pHtmlDoc); if (hr) goto Cleanup; // Query for IPersistStreamInit // hr = pHtmlDoc->QueryInterface(IID_IPersistStreamInit, (void**)&pPersistStreamInit); if (hr) goto Cleanup;
Having obtained the IPersistStreamInit pointer, you can now use the Init and Load methods of this interface to initialize and load an HTML document from a stream. The Init method initializes the stream to a known state, while the Load method loads the data from the stream.
In the following sample code, the szHTMLText parameter is used to hold two streams of data, and the nToggle variable is used to toggle between the two streams.
// Tell the document we'll be reinitializing it. // hr = pPersistStreamInit->InitNew(); if (hr) goto Cleanup; // Load the contents of the stream. // hr = pPersistStreamInit->Load(pStream); Cleanup: if (pHtmlDoc) pHtmlDoc->Release(); if (pPersistStreamInit) pPersistStreamInit->Release(); return hr;
Note With the introduction of Microsoft® Internet Explorer 5, any number of calls to the Load method of the IPersist interfaces can be supported. In earlier versions, only a single call can be supported.
The following article provides information about Microsoft® Visual Studio® development:
The following articles provide information about COM: