65.9K
CodeProject is changing. Read more.
Home

Programmatically scrolling WebBrowser control from Visual C/C++

starIconstarIconstarIconstarIconstarIcon

5.00/5 (15 votes)

Aug 23, 2001

viewsIcon

260716

Article describes how to obtain IHTML interfaces to prrogrammatically scroll WebBrowser control from Visual C/C++.

Introduction

For some time I struggled to do these simple tasks in Visual C++:

  1. How to get browser window to scroll programmatically?

    It does not accept Windows scroll messages. Calling the MFC GetScrollInfo APIs does not do anything. But there is a way.

  2. To scroll we use IHTMLElement2 API get_scrollTop/put_scrollTop... but how do I obtain IHTMLElement2?

The way is a bit obscure...

Now, the code

    //
    // All this code does is what
    // "m_browser.Document.Body.ScrollTop = 100;"
    // does in VB. Gotta love COM in C++.
    //

    // let's say m_browser is the WebBrowser's member variable.

    HRESULT hr;

    // get the document dispatch from browser
    IDispatch *pDisp = m_browser.GetDocument();
    ASSERT( pDisp ); //if NULL, we failed
    
    // get document interface
    IHTMLDocument2 *pDocument = NULL;
    hr = pDisp->QueryInterface( IID_IHTMLDocument2, (void**)&pDocument );
    ASSERT( SUCCEEDED( hr ) );
    ASSERT( pDocument );

    //
    // this is the trick! 
    // take the body element from document...
    //
    IHTMLElement *pBody = NULL;
    hr = pDocument->get_body( &pBody );
    ASSERT( SUCCEEDED( hr ) );
    ASSERT( pBody );

    // from body we can get element2 interface,
    // which allows us to do scrolling
    IHTMLElement2 *pElement = NULL;
    hr = pBody->QueryInterface(IID_IHTMLElement2,(void**)&pElement);
    ASSERT(SUCCEEDED(hr));
    ASSERT( pElement );

    // now we are ready to scroll
    // scroll down to 100th pixel from top
    pElement->put_scrollTop( 100 ); 
    
    // try to get the whole page size - but the returned number
    // is not allways correct. especially with pages that use dynamic html
    // tricks...
    long scroll_height; 
    pElement->get_scrollHeight( &s );

    // we can use this workaround!
    long real_scroll_height;
    pElement->put_scrollTop( 20000000 ); // ask to scroll really far down...
    pElement->get_scrollTop( &real_scroll_height );
    real_scroll_height += window_height; // will return the scroll height
    // for the first visible pixel, to get whole html page size must
    // add the window's height... (to obtain window_height is
    // left as an exercise for the reader)


    // print to debug output
    TRACE( "real scroll height: %ld, get_scrollHeight: %ld\n", 
                     real_scroll_height, scroll_height );

And there we have it.