Click here to Skip to main content
15,885,366 members
Articles / Desktop Programming / MFC
Article

Detecting the IE Refresh button using IWebBrowser2 and DWebBrowserEvents2 events.

Rate me:
Please Sign up or sign in to vote.
4.61/5 (17 votes)
13 Oct 20042 min read 273.8K   6K   39   47
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


Written By
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 Pin
Elmue19-May-13 10:32
Elmue19-May-13 10:32 
QuestionIncorrect handling of Post data Pin
Elmue17-May-13 13:27
Elmue17-May-13 13:27 
GeneralMy vote of 5 Pin
Elmue17-May-13 12:07
Elmue17-May-13 12:07 
QuestionC# too? Pin
Keith L Robertson12-Mar-10 12:07
Keith L Robertson12-Mar-10 12:07 
GeneralThank you, thank you very much. Pin
caesten5-Jul-09 5:15
caesten5-Jul-09 5:15 
Questionhow to detect the print event? Pin
梁城3-Jan-09 15:27
梁城3-Jan-09 15:27 
Answersolution Pin
mojo.ssp4-May-08 7:59
mojo.ssp4-May-08 7:59 
GeneralRe: solution Pin
Keith L Robertson12-Mar-10 11:42
Keith L Robertson12-Mar-10 11:42 
GeneralRe: solution Pin
mojo.ssp14-Mar-10 3:06
mojo.ssp14-Mar-10 3:06 
GeneralRe: solution Pin
Keith L Robertson17-Mar-10 10:37
Keith L Robertson17-Mar-10 10:37 
Questionhow to detect the event for ie? [modified] Pin
Armandopoulos30-Nov-07 2:01
Armandopoulos30-Nov-07 2:01 
Generalcatches javascript image downloads Pin
sunwuong81-Nov-07 6:43
sunwuong81-Nov-07 6:43 
GeneralWorks well, but not perfectly. Pin
villecoder9-Oct-07 12:44
villecoder9-Oct-07 12:44 
GeneralRe: Works well, but not perfectly. Pin
conman11022-Oct-07 8:37
conman11022-Oct-07 8:37 
GeneralRe: Works well, but not perfectly. Pin
villecoder22-Oct-07 14:29
villecoder22-Oct-07 14:29 
GeneralRe: Works well, but not perfectly. Pin
conman11023-Oct-07 1:16
conman11023-Oct-07 1:16 
GeneralInsert a dummy stylesheet Pin
Mingaliu24-Aug-07 15:05
Mingaliu24-Aug-07 15:05 
GeneralRe: Insert a dummy stylesheet Pin
villecoder9-Oct-07 12:48
villecoder9-Oct-07 12:48 
Questionhow to detect the download events? Pin
kamalraaja23-Jul-06 19:05
kamalraaja23-Jul-06 19:05 
Generalslightly off-topic question Pin
Irek Zielinski18-Mar-06 10:38
Irek Zielinski18-Mar-06 10:38 
Generalanother (common) solution Pin
Mike Melnikov19-Oct-04 20:19
Mike Melnikov19-Oct-04 20:19 
GeneralRe: another (common) solution Pin
Sheng Jiang 蒋晟10-Jul-05 14:39
Sheng Jiang 蒋晟10-Jul-05 14:39 
GeneralRe: another (common) solution Pin
Member 146094310-Aug-05 11:09
Member 146094310-Aug-05 11:09 
GeneralRe: another (common) solution Pin
Sheng Jiang 蒋晟19-Apr-06 3:49
Sheng Jiang 蒋晟19-Apr-06 3:49 
GeneralCould it be work on an ActiveX Pin
rc28610125-Mar-04 14:17
rc28610125-Mar-04 14:17 

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

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