Home Search Contact us About us
Title Handling event in an embedded web broswer control.
Summary A web browser is a powerful tool when embedded in you’re application. This article covers how to catch keyboard and other events in CHtmlView, CHtmlCtrl and Microsoft Web Browser Control.
Contributor John McTainsh
Published 23-Mar-2001
Last updated 23-Mar-2001
Page rating   55% for 33 votes Useless Brilliant

Description.

This article will cover how to catch events generated by a Web Browser embedded in your application. This browser could be a CHTMLView or an ActiveX control. In bother cases this will be done using the IHTMLDocument2 interface. I will cover Keyboard events here but other event can also be caught in the same manner.

Setting the event handler.

The event handler I am using is provided in MDSN article ID: Q253915. It is probably copyright so you must get it from there yourself. 

  • Place it in a file called FunctionObject.h. Include this at the top of the cpp file you want to put the event in.
    #include "FunctionObject.h"
    
  • Add a function prototype to the class that will receive the event.
            void KeyDownCallback( DISPID id, VARIANT* pVarResult );
    
  • Add the implementation in the cpp file.
    void CSomeClass::KeyDownCallback( DISPID id, VARIANT* pVarResult )
    {
        ...
    }
    
  • Once the HTML document is ready assign the handler.
        IDispatch* pDispatch = GetHtmlDocument();
        //
        //Only if a resource or web page is loaded can we get the document
        //
        ASSERT( pDispatch );
        if( pDispatch != NULL )
        {
            IHTMLDocument2* pHtmlDoc;
            HRESULT hr = pDispatch->QueryInterface( __uuidof( IHTMLDocument2 ), (void**)&pHtmlDoc );
            pDispatch->Release();
            ASSERT( SUCCEEDED( hr ) );
            LPDISPATCH dispFO = CFunctionObject<CSomeClass>::CreateEventFunctionObject(this, 
                12345, KeyDownCallback );
            VARIANT vIn;                            
            V_VT(&vIn) = VT_DISPATCH; 
            V_DISPATCH(&vIn) = dispFO; 
            HRESULT hr = pHtmlDoc->put_onkeydown( vIn );
            ASSERT( SUCCEEDED( hr ) );
            pHtmlDoc->Release();
        }
    
  • Remember to release the handler before destroying the web browser control.
        IDispatch* pDispatch = GetHtmlDocument();
        ASSERT( pDispatch );
        if( pDispatch != NULL )
        {
            IHTMLDocument2* pHtmlDoc;
            HRESULT hr = pDispatch->QueryInterface( __uuidof( IHTMLDocument2 ), (void**)&pHtmlDoc );
            pDispatch->Release();
            VARIANT varNull = { 0 }; 
            varNull.vt = VT_NULL;
            HRESULT hr = pHtmlDoc->put_onkeydown( varNull );
            ASSERT( SUCCEEDED( hr ) );
            pHtmlDoc->Release();
        }
    

Determining The Event Details.

When the event occurs, no information about the event is passes into the handler. To determine the details of the event we read the IHTMLEventObj. If we do not want the default processing of the event we must also return VARIANT_FALSE in pVarResult. The following catches the {Enter} key press and inserts a line feed into the HTML.

// ***************************************************************************
//DESCRIPTION:
//      Catch the key down event to try Enter and Tab
//PARAMS:
//      pVarResult      Set to false to stop processing event
//CREATED:
//      20-3-2001, 5:53:11 PM by john@mctainsh.com
// ***************************************************************************
void CSomeClass::KeyDownCallback( DISPID id, VARIANT* pVarResult )
{
    TRACE( _T("CSomeClass::KeyDownCallback( id, pVarResult)\n") );

    IDispatch* pDispatch = GetHtmlDocument();
    ASSERT( pDispatch );
    if( pDispatch != NULL )
    {
        IHTMLDocument2* pHtmlDoc;
        HRESULT hr = pDispatch->QueryInterface( __uuidof( IHTMLDocument2 ), (void**)&pHtmlDoc );
        pDispatch->Release();
        
        //
        //Determine the key pressed
        //
        IHTMLWindow2*     pWindow;
        IHTMLEventObj* pEvent;
     
        HRESULT hr = pHtmlDoc->get_parentWindow(&pWindow);
        ASSERT( SUCCEEDED( hr ) );
    
        hr = pWindow->get_event(&pEvent);
        ASSERT( SUCCEEDED( hr ) );
        pWindow->Release();
        long nKey;
        hr = pEvent->get_keyCode( &nKey );
        ASSERT( SUCCEEDED( hr ) );
        pEvent->Release();

        //
        //Process the Key Enter or Tab
        //
        switch( nKey )
        {
        case VK_RETURN:
            if( m_nIDNextTab == 0 )
            {
                //Do not process further
                V_VT(pVarResult) = VT_BOOL; 
                V_BOOL(pVarResult) = FALSE; 
                
                //Insert a BR tag
                IHTMLSelectionObject *pSel;
                hr = pHtmlDoc->get_selection(&pSel);
                ASSERT( SUCCEEDED( hr ) );
                IDispatch* pDisp;
                
                hr = pSel->createRange( &pDisp );
                pSel->Release();
                ASSERT( SUCCEEDED( hr ) );
                
                IHTMLTxtRange* pTr;
                hr = pDisp->QueryInterface( __uuidof( IHTMLTxtRange ), (void**)&pTr );
                pDisp->Release();
                ASSERT( SUCCEEDED( hr ) );
                
                long nAmount;
                hr = pTr->pasteHTML( L"--An Line feed goes here--" );
                
                pTr->move( L"character", 0, &nAmount );
                pTr->select();
                
                ASSERT( SUCCEEDED( hr ) );
                pTr->Release();
            }
            break;
        }
        pHtmlDoc->Release();
    }       
}
Comments Date
Alternative 24-Jun-2007 Greg
Its probably easier to trap IHTMLEditDesigner::PreHandleEvent where DISPID=DISPID_HTMLELEMENTEVENTS2_ONKEYPRESS

The two methods will receive the exact same keystroke events. The real question is, why do function keys not trigger an event?
Home Search Contact us About us