![]() |
General Programming »
Internet / Network »
General
Advanced
Detecting the IE Refresh button using IWebBrowser2 and DWebBrowserEvents2 events.By SteveFoxAn article explaining how to capture a click on Internet Exporer's Refresh button, using DWebBrowserEvents2. |
C++/CLI, VC6, .NET, Win2K, WinXP, MFC, Dev
|
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
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.
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.
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; }
The tricky part is actually working out if the refresh button was hit. The logic goes as follows:
BeforeNavigate2() is called we add 1 to a page counter m_nPageCounter ++;
DocumentComplete(), we take 1 from the page counter m_nPageCounter --;
DownloadBegin(), we check if m_nPageCounter == 0. If so we know it's a refresh page call.
m_nObjCounter ++;
true to note it's a refresh call, m_bIsRefresh = true;
DownloadEnd() we decrease the counter from DownloadBegin. m_nObjCounter --;
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...)
My first release...
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 14 Oct 2004 Editor: Nishant Sivakumar |
Copyright 2003 by SteveFox Everything else Copyright © CodeProject, 1999-2009 Web17 | Advertise on the Code Project |