Click to return to the Reusing Browser Technology home page    
IHTMLEvents Interface     Using the Web Browser Com...     IHTMLEvents2 Interface    
Web Workshop  |  Reusing Browser Technology

Using the Web Browser Component to Load an HTML Document from a Stream


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++® Non-MSDN link.

This article is divided into the following sections:

Navigating the Browser to about:blank

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);

Obtaining a Pointer to the Object Model

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();
}

Using QueryInterface to Obtain IPersistStreamInit

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;

Using IPersistStreamInit to Load Your Document from a Stream

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.

Related Topics

The following article provides information about Microsoft® Visual Studio® development:

The following articles provide information about COM:



Back to topBack to top

Did you find this topic useful? Suggestions for other topics? Write us!

© 1999 Microsoft Corporation. All rights reserved. Terms of use.