Loading HTML content from a Stream

The IPersistStreamInit interface, and its associated methods, can be used to load HTML content from a stream using the WebBrowser control and Microsoft Visual C++.

This article discusses the steps required to load HTML content from a stream and is divided into the following sections.

  • Navigating to about:blank
  • Availability of the DHTML Object Model
  • Using QueryInterface to Obtain the IPersistStreamInit Interface
  • Using the IPersistStreamInit Interface to Load HTML Content
  • Offline Reading
  • Related topics

The IWebBrowser2::Navigate2 method of the IWebBrowser2 interface enables you to navigate the browser to a URL. In the following sample code, the IWebBrowser2::Navigate2 method is used to navigate to the about:blank page. Navigating to this empty page ensures that MSHTML is loaded and that the HTML elements are available through the Dynamic HTML (DHTML) Object Model.

This example demonstrates how to navigate the WebBrowser control to an empty page. The variable m_pBrowser contains the IWebBrowser2 interface pointer obtained from the WebBrowser control.

m_pBrowser->Navigate2( _T("about:blank"), NULL, NULL, NULL, NULL );

Availability of the DHTML Object Model

The DHTML Object Model is used to access and manipulate the contents of an HTML page and is not available until the page is loaded. Your application determines that a page is loaded by handling the DWebBrowserEvents2::DocumentComplete event of the WebBrowser control. This event may be fired once for each frame in the page, and once when the top frame of the document is loaded. You can determine if the DWebBrowserEvents2::DocumentComplete event is for the top frame by comparing the IDispatch interface pointer passed by this event with that of the WebBrowser control.

This sample handler code for the WebBrowser DWebBrowserEvents2::DocumentComplete event demonstrates how to determine if this event is for the top frame, which indicates that the HTML page has loaded. This sample also demonstrates how to create a stream from a block of memory—in this case a string that contains the HTML content to be displayed.

void myObject::DocumentComplete(LPDISPATCH pDisp, VARIANT* URL)
    HRESULT hr;
    IUnknown* pUnkBrowser = NULL;
    IUnknown* pUnkDisp = NULL;
    IStream* pStream = NULL;
    static TCHAR szHTMLText[] = "<html><h1>Stream Test</h1><p>This HTML content is/
       being loaded from a stream.</html>";

    // Is this the DocumentComplete event for the top frame window?
    // Check COM identity: compare IUnknown interface pointers.
    hr = m_pBrowser->QueryInterface( IID_IUnknown,  (void**)&pUnkBrowser );
    if ( SUCCEEDED(hr) )
        hr = pDisp->QueryInterface( IID_IUnknown,  (void**)&pUnkDisp );
        if ( SUCCEEDED(hr) )
            if ( pUnkBrowser == pUnkDisp )
            {   // This is the DocumentComplete event for the top 
                //   frame - page is loaded!
                // Create a stream containing the HTML.
                // Alternatively, this stream may have been passed to us.
                size_t = cchLength;
                //  TODO: Safely determine the length of szHTMLText in TCHAR.
                hHTMLText = GlobalAlloc( GPTR, cchLength+1 );
                if ( hHTMLText )
                    size_t cchMax = 256;
                    StringCchCopy((TCHAR*)hHTMLText, cchMax + 1, szHTMLText);
                    //  TODO: Add error handling code here.

                    hr = CreateStreamOnHGlobal( hHTMLText, TRUE, &pStream );
                    if ( SUCCEEDED(hr) )
                       // Call the helper function to load the browser from the stream.
                       LoadWebBrowserFromStream( m_pBrowser, pStream  );
                    GlobalFree( hHTMLText );

Using QueryInterface to Obtain the IPersistStreamInit Interface

The IWebBrowser2::get_Document property on the WebBrowser control retrieves the document object that represents the DHTML Object Model for the top frame. MSHTML implements the IPersistStreamInit interface to provide the ability to load and save HTML using a stream, through the document object. The IDispatch interface for the document object can be queried for the IPersistStreamInit interface pointer using QueryInterface with an identifier of IID_IPersistStreamInit, as shown in the following code example.

HRESULT LoadWebBrowserFromStream(IWebBrowser* pWebBrowser, IStream* pStream)
IDispatch* pHtmlDoc = NULL;
IPersistStreamInit* pPersistStreamInit = NULL;

    // Retrieve the document object.
    hr = pWebBrowser->get_Document( &pHtmlDoc );
    if ( SUCCEEDED(hr) )
        // Query for IPersistStreamInit.
        hr = pHtmlDoc->QueryInterface( IID_IPersistStreamInit,  (void**)&pPersistStreamInit );
        if ( SUCCEEDED(hr) )
            // Initialize the document.
            hr = pPersistStreamInit->InitNew();
            if ( SUCCEEDED(hr) )
                // Load the contents of the stream.
                hr = pPersistStreamInit->Load( pStream );

Using the IPersistStreamInit Interface to Load HTML Content

The IPersistStreamInit interface has InitNew and Load methods that are used to initialize and load an HTML document from a stream. The InitNew method initializes the stream to a known state and the Load method loads the HTML content from the stream.

In the previous sample code, the HTML document is initialized and the HTML content is loaded from the stream.

Note  In Microsoft Internet Explorer 5, more than one call to the Load method of the IPersist interfaces is supported. In earlier versions, only one call to Load per instance of MSHTML is supported.


Offline Reading

The following articles provide information about the Component Object Model (COM).

  • Inside OLE, 2nd Edition, by Kraig Brockschmidt (Microsoft Press)
  • Understanding ActiveX and OLE, by David Chappell (Microsoft Press)
  • Inside COM, by Dale Rogerson (Microsoft Press)

Other Resources

Visual Studio Developer Center

The Component Object Model