« 2007年06月 | メイン | 2007年08月 »

2007年07月 アーカイブ

2007年07月17日

IE6/7対応のBHOでページのリロードを確実に取得する

Internet Explorer用のプラグイン拡張BHO(Browser Helper Object)を開発していると、いろいろ理不尽に思えることがたくさんあります。

その最たるものが、ページのリロードを通知してくれるイベントが無いこと。
DocumentComplete来るんじゃないの? と思ってると、そんなことは無いし、Webを漁っていくと、DownloadBegin/Completeイベントをカウントするとできるヨ! というサンプルがいくつか見つかりますが、これもIE7やいまどきのiframe使いまくりなページに出会うとエラー続出です。 

そんなわけで、イベントのタイミングを見極めて、これならわりと安定して動くんじゃない? という状態になったので、あまり縁がある人もいないでしょうが、ご参考までに。(キーイベントとかを拾った方がいいかもですけどね...)

メインフレームのDocumentCompleteが来ても、ブラウザがbusyだと、再度DocumentCompleteが発生する場合があるようです。
このあたりが対処療法的ではあるのですが、いちおうカウンターが暴走しないようにはなってます。

見やすいようにあえてswitch文で...。


// to detect Internet Expolorer page refreshing in BHO (with IE6/7)

inline bool IsMainFrame(IWebBrowser2 *pWebBrowser2)
{
return pWebBrowser2 == m_spWebBrowserMainFrame;
}

HRESULT Bho::Invoke(DISPID dispidMember, REFIID riid, LCID lcid
, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pvarResult
, EXCEPINFO* pExcepInfo, UINT* puArgErr)
{
if (!pDispParams)
return E_INVALIDARG;
switch(dispidMember)
{
case DISPID_DOCUMENTCOMPLETE:
if (pDispParams->cArgs != 2)
return DISP_E_BADPARAMCOUNT;
if (pDispParams->rgvarg[1].vt == VT_DISPATCH
&& pDispParams->rgvarg[0].vt == (VT_BYREF | VT_VARIANT)
    && pDispParams->rgvarg[0].pvarVal->vt == VT_BSTR))
{
CComQIPtr<IWebBrowser2, &IID_IWebBrowser2>
spWebBrowserPage = V_DISPATCH(&pDispParams->rgvarg[1]);

VARIANT_BOOL fBusy;
spWebBrowserPage->get_Busy(&fBusy);
if (!fBusy || !IsMainFrame(spWebBrowserPage))
{
if (m_nPageCounter > 0)
m_nPageCounter--;

// Main frame document complete normally
OnDocumentComplete(spWebBrowserPage
, *pDispParams->rgvarg[0].pvarVal->bstrVal);
}
}
break;
case DISPID_BEFORENAVIGATE2:
if (pDispParams->cArgs != 7)
return DISP_E_BADPARAMCOUNT;
if (pDispParams->rgvarg[6].vt == VT_DISPATCH)
{
CComQIPtr<IWebBrowser2, &IID_IWebBrowser2>
spWebBrowserPage = V_DISPATCH(&pDispParams->rgvarg[6]);
if (IsMainFrame(spWebBrowserPage))
{
m_nPageCounter = 0;
if (m_fIsRefresh)
m_fIsRefresh = false;
}
}
m_nPageCounter++;
break;
case DISPID_DOWNLOADBEGIN:
m_nObjCounter++;
if (m_nPageCounter == 0)
m_fIsRefresh = true;
break;
case DISPID_DOWNLOADCOMPLETE:
if (m_nObjCounter > 0)
m_nObjCounter--;
if(m_fIsRefresh && m_nObjCounter == 0)
{
// Refrash main frame here!
m_fIsRefresh = false;
CComBSTR bstrUrl;
m_spWebBrowserMainFrame->get_LocationURL(&bstrUrl);
OnDocumentComplete(m_spWebBrowserMainFrame
, bstrUrl.m_str);
}
break;
case DISPID_ONQUIT:
OnQuit();
break;
default:
break;
}
return S_OK;
}





何か問題が見つかったり、新しい手口を見つけたら更新する予定。
ここおかしいよ、とかうまく動かない点などありましたらご一報を。

About 2007年07月

2007年07月にブログ「Neutral Scent」に投稿されたすべてのエントリーです。過去のものから新しいものへ順番に並んでいます。

前のアーカイブは2007年06月です。

次のアーカイブは2007年08月です。

他にも多くのエントリーがあります。メインページアーカイブページも見てください。