Click here to Skip to main content
Click here to Skip to main content

Detecting the IE Refresh button using IWebBrowser2 and DWebBrowserEvents2 events.

, 13 Oct 2004
Rate this:
Please Sign up or sign in to vote.
An article explaining how to capture a click on Internet Exporer's Refresh button, using DWebBrowserEvents2.

Introduction

If you have ever tried to capture an event from the Internet Explorer web browser when a user clicks the Refresh button, you will know it is not easy. Capturing Internet Explorer events is generally not easy using MFC or COM. I have created a class that I use to capture DWebBrowserEvents2 events and the logic needed to detect a page refresh. There are no events specifically sent for a page refresh and the normal events you check for do not work. So you have to use a work around. My class is called CIEComCtrlSink. It is derived from CCmdTarget and is used to capture DWebBrowserEvents2 events. You can also use the logic to solve this problem in JavaScript etc.

Background

I did some searching on the Internet for a solution to this Microsoft bug/issue and only found some talk of a workout in Google newsgroups. So after I got it working, I thought I better throw the solution up on CodeProject.

Using the code

In the sample application, I just used an MFC Wizard to create a new Dialog project. In the file IERefreshSampleDlg.cpp I respond to a button click and create a new web browser object and advise it we want events from it.

// create the browser and event sink
BOOL CIERefreshSampleDlg::CreateMyIEBrowser()
{
    if(m_pMyIESink != NULL)
    {
        AfxMessageBox("Sorry just one browser in this sample :)");
        return false;
    }

    m_pMyIESink = new CIEComCtrlSink();
    m_pMyIESink->m_pParent = this;
    BOOL bOK = m_pMyIESink->MyAdviseSink();

    return bOK;
}

The CIEComCtrlSink class does all the work. It is derived from CCmdTarget so we can get events from DWebBrowserEvents2 object.

// start capture of DWebBrowserEvents2 events
BOOL CIEComCtrlSink::MyAdviseSink()
{
    // create the web browser using IWebBrowser2
    HRESULT hr = CoCreateInstance(CLSID_InternetExplorer,
                               NULL,
                               CLSCTX_LOCAL_SERVER,
                               IID_IWebBrowser2,
                               (void**)&m_pWebBrowser2);

    if(!SUCCEEDED(hr))
    {
        CString strMsg;
        strMsg.Format("Failed to create object error = %d",(int)hr);
        AfxMessageBox(strMsg);
        return false;
    }
    // get an interface to IWebBrowserApp so we can set the toolbars we want
    hr = m_pWebBrowser2->QueryInterface(IID_IWebBrowserApp,
                                              (void**)&m_pIEApp);
    hr = m_pIEApp->put_StatusBar(true);
    hr = m_pIEApp->put_ToolBar(true);
    hr = m_pIEApp->put_MenuBar(true);

    long hIE;
    // get a window handle so we can resize and show the browser window.
    hr = m_pWebBrowser2->get_HWND(&hIE);
    if(!SUCCEEDED(hr))
    {
        CString strMsg;
        strMsg.Format("Failed to create object error = %d",(int)hr);
        AfxMessageBox(strMsg);
        return FALSE;
    }
    // use CWnd to make showing the window etc easy
    m_wndWebBrowser.Attach((HWND)hIE);
    m_wndWebBrowser.EnableScrollBar(SB_BOTH, ESB_DISABLE_BOTH);
    m_wndWebBrowser.ShowWindow(SW_NORMAL);

    // navigate to a URL
    Navigate2("http://www.stevefoxover.com");

    // advise the browser to send events here
    LPUNKNOWN pUnkSink = GetIDispatch(FALSE);
    AfxConnectionAdvise((LPUNKNOWN)m_pWebBrowser2, 
      DIID_DWebBrowserEvents2,pUnkSink,FALSE,&m_dwCookie); 

    return TRUE;
}

Points of interest

The tricky part is actually working out if the refresh button was hit. The logic goes as follows:

  • Each time BeforeNavigate2() is called we add 1 to a page counter m_nPageCounter ++;
  • Each call to DocumentComplete(), we take 1 from the page counter m_nPageCounter --;
  • Each call to DownloadBegin(), we check if m_nPageCounter == 0. If so we know it's a refresh page call.
  • We also add to an object counter here m_nObjCounter ++;
  • Also we set a member variable to true to note it's a refresh call, m_bIsRefresh = true;
  • On DownloadEnd() we decrease the counter from DownloadBegin. m_nObjCounter --;
  • If m_nObjCounter is zero and we are in refresh mode we know that the refreshed page has loaded. if(m_bIsRefresh && m_nObjCounter == 0)

Clear as mud? Just compile the sample application and put break points in:

  • CIEComCtrlSink::BeforeNavigate2()
  • CIEComCtrlSink::DocumentComplete()
  • CIEComCtrlSink::DownloadBegin()
  • CIEComCtrlSink::DownloadEnd()

You will then see what is called and when from Internet Explorer. IE never calls BeforeNavigate2() or DocumentComplete() on a page refresh. (Bad IE...)

History

My first release...

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

SteveFox
Web Developer
United States United States
I have spent many years working on projects involving data and large file transportation via the Internet. For the last 5 years I have also worked with digital video. I have created applications that encode, transcode, publish, deliver via progressive download with download acceleration, track and protect digital video.

Comments and Discussions

 
NewsImportant note PinmemberElmue19-May-13 10:32 
QuestionIncorrect handling of Post data [modified] PinmemberElmue17-May-13 13:27 
GeneralMy vote of 5 [modified] PinmemberElmue17-May-13 12:07 
QuestionC# too? PinmemberKeith L Robertson12-Mar-10 12:07 
GeneralThank you, thank you very much. Pinmembercaesten5-Jul-09 5:15 
Questionhow to detect the print event? PinmemberMember #44671673-Jan-09 15:27 
Answersolution Pinmembermojo.ssp4-May-08 7:59 
GeneralRe: solution PinmemberKeith L Robertson12-Mar-10 11:42 
GeneralRe: solution Pinmembermojo.ssp14-Mar-10 3:06 
GeneralRe: solution PinmemberKeith L Robertson17-Mar-10 10:37 
Questionhow to detect the event for ie? [modified] PinmemberArmandopoulos30-Nov-07 2:01 
Generalcatches javascript image downloads Pinmembersunwuong81-Nov-07 6:43 
GeneralWorks well, but not perfectly. PinmemberZinkyu9-Oct-07 12:44 
GeneralRe: Works well, but not perfectly. Pinmemberconman11022-Oct-07 8:37 
GeneralRe: Works well, but not perfectly. PinmemberZinkyu22-Oct-07 14:29 
GeneralRe: Works well, but not perfectly. Pinmemberconman11023-Oct-07 1:16 
GeneralInsert a dummy stylesheet PinmemberMingaliu24-Aug-07 15:05 
GeneralRe: Insert a dummy stylesheet PinmemberZinkyu9-Oct-07 12:48 
Questionhow to detect the download events? Pinmemberkamalraaja23-Jul-06 19:05 
Generalslightly off-topic question PinmemberIrek Zielinski18-Mar-06 10:38 
Generalanother (common) solution PinmemberMike Melnikov19-Oct-04 20:19 
GeneralRe: another (common) solution PinmemberJIANG, Sheng[MVP]10-Jul-05 14:39 
GeneralRe: another (common) solution Pinmemberjeremy.w10-Aug-05 11:09 
GeneralRe: another (common) solution PinmemberJIANG, Sheng[MVP]19-Apr-06 3:49 
GeneralCould it be work on an ActiveX Pinmemberrc28610125-Mar-04 14:17 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web02 | 2.8.140721.1 | Last Updated 14 Oct 2004
Article Copyright 2003 by SteveFox
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid