IDispatchを継承したクラスを実装して、IConnectionPointのAdvise()関数で接続 すると、ブラウザからのイベントを取得する事ができます。
#include <tchar.h>
#include <shlobj.h>
#include <comdef.h>
#include <comutil.h>
#include <iostream>
#include <ExDispid.h>
using namespace std;
// I/F解放用マクロ
#define SAFE_RELEASE( p1 ) if ( p1 ) { p1->Release(); p1 = NULL; }
/*
イベントをディスパッチさせる為にIDispatchから派生させたクラス
*/
class EventSink_CL : public IDispatch
{
ULONG m_qRefCounter;
public:
// コンストラクタ
EventSink_CL()
: m_qRefCounter( 1 )
{
}
// デストラクタ
virtual ~EventSink_CL()
{
}
// AddRef
virtual STDMETHODIMP_(ULONG) AddRef(void)
{
// 参照カウンタ+1
return( ++m_qRefCounter );
}
// Release
virtual STDMETHODIMP_(ULONG) Release(void)
{
// 参照カウンタ-1
if ( 0 == --m_qRefCounter ) {
// 参照カウンタが0になったら自身を破棄する
delete this;
}
// 参照カウンタを返す
return( m_qRefCounter );
}
// QueryInterface
virtual STDMETHODIMP QueryInterface( REFIID riid, void **ppvOut )
{
HRESULT hResult = E_NOINTERFACE;
// IID_IUnknownもしくはIID_IDispatchのI/Fは保有している
if( IsEqualIID( riid, IID_IUnknown ) || IsEqualIID( riid, IID_IDispatch ) ) {
// 参照カウンタ+1
this->AddRef();
// I/Fを返す。
*ppvOut = reinterpret_cast<IDispatch*>( this );
// 正常終了
hResult = S_OK;
} else {
// 指定されたI/Fは保有していない。
*ppvOut = NULL;
}
// 戻り値を返す
return( hResult );
}
// GetTypeInfoCount
virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount
(
/* [out] */ __RPC__out UINT *pctinfo
)
{
return E_NOTIMPL;
}
// GetTypeInfo
virtual HRESULT STDMETHODCALLTYPE GetTypeInfo
(
/* [in] */ UINT iTInfo,
/* [in] */ LCID lcid,
/* [out] */ __RPC__deref_out_opt ITypeInfo **ppTInfo
)
{
return E_NOTIMPL;
}
// GetIDsOfNames
virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames
(
/* [in] */ __RPC__in REFIID riid,
/* [size_is][in] */ __RPC__in_ecount_full(cNames) LPOLESTR *rgszNames,
/* [range][in] */ UINT cNames,
/* [in] */ LCID lcid,
/* [size_is][out] */ __RPC__out_ecount_full(cNames) DISPID *rgDispId
)
{
return E_NOTIMPL;
}
// Invoke
virtual /* [local] */ HRESULT STDMETHODCALLTYPE Invoke
(
/* [in] */ DISPID dispIdMember,
/* [in] */ REFIID riid,
/* [in] */ LCID lcid,
/* [in] */ WORD wFlags,
/* [out][in] */ DISPPARAMS *pDispParams,
/* [out] */ VARIANT *pVarResult,
/* [out] */ EXCEPINFO *pExcepInfo,
/* [out] */ UINT *puArgErr
)
{
/*
イベントを受信するとここが呼び出されます
dispidMemberにイベントの種別が入ります。
パラメータはpDispParamsに入ります。
*/
// イベント名の表示
switch( dispIdMember ) {
case DISPID_BEFORENAVIGATE:
cout << "DISPID_BEFORENAVIGATE" << endl; break;
case DISPID_NAVIGATECOMPLETE:
cout << "DISPID_NAVIGATECOMPLETE" << endl; break;
case DISPID_STATUSTEXTCHANGE:
cout << "DISPID_STATUSTEXTCHANGE" << endl; break;
case DISPID_QUIT:
cout << "DISPID_QUIT" << endl; break;
case DISPID_DOWNLOADCOMPLETE:
cout << "DISPID_DOWNLOADCOMPLETE" << endl; break;
case DISPID_COMMANDSTATECHANGE:
cout << "DISPID_COMMANDSTATECHANGE" << endl; break;
case DISPID_DOWNLOADBEGIN:
cout << "DISPID_DOWNLOADBEGIN" << endl; break;
case DISPID_NEWWINDOW:
cout << "DISPID_NEWWINDOW" << endl; break;
case DISPID_PROGRESSCHANGE:
cout << "DISPID_PROGRESSCHANGE" << endl; break;
case DISPID_WINDOWMOVE:
cout << "DISPID_WINDOWMOVE" << endl; break;
case DISPID_WINDOWRESIZE:
cout << "DISPID_WINDOWRESIZE" << endl; break;
case DISPID_WINDOWACTIVATE:
cout << "DISPID_WINDOWACTIVATE" << endl; break;
case DISPID_PROPERTYCHANGE:
cout << "DISPID_PROPERTYCHANGE" << endl; break;
case DISPID_TITLECHANGE:
cout << "DISPID_TITLECHANGE" << endl; break;
case DISPID_TITLEICONCHANGE:
cout << "DISPID_TITLEICONCHANGE" << endl; break;
case DISPID_FRAMEBEFORENAVIGATE:
cout << "DISPID_FRAMEBEFORENAVIGATE" << endl; break;
case DISPID_FRAMENAVIGATECOMPLETE:
cout << "DISPID_FRAMENAVIGATECOMPLETE" << endl; break;
case DISPID_FRAMENEWWINDOW:
cout << "DISPID_FRAMENEWWINDOW" << endl; break;
case DISPID_BEFORENAVIGATE2:
cout << "DISPID_BEFORENAVIGATE2" << endl; break;
case DISPID_NEWWINDOW2:
cout << "DISPID_NEWWINDOW2" << endl; break;
case DISPID_NAVIGATECOMPLETE2:
cout << "DISPID_NAVIGATECOMPLETE2" << endl; break;
case DISPID_ONQUIT:
cout << "DISPID_ONQUIT" << endl; break;
case DISPID_ONVISIBLE:
cout << "DISPID_ONVISIBLE" << endl; break;
case DISPID_ONTOOLBAR:
cout << "DISPID_ONTOOLBAR" << endl; break;
case DISPID_ONMENUBAR:
cout << "DISPID_ONMENUBAR" << endl; break;
case DISPID_ONSTATUSBAR:
cout << "DISPID_ONSTATUSBAR" << endl; break;
case DISPID_ONFULLSCREEN:
cout << "DISPID_ONFULLSCREEN" << endl; break;
case DISPID_DOCUMENTCOMPLETE:
cout << "DISPID_DOCUMENTCOMPLETE" << endl; break;
case DISPID_ONTHEATERMODE:
cout << "DISPID_ONTHEATERMODE" << endl; break;
case DISPID_ONADDRESSBAR:
cout << "DISPID_ONADDRESSBAR" << endl; break;
case DISPID_WINDOWSETRESIZABLE:
cout << "DISPID_WINDOWSETRESIZABLE" << endl; break;
case DISPID_WINDOWCLOSING:
cout << "DISPID_WINDOWCLOSING" << endl; break;
case DISPID_WINDOWSETLEFT:
cout << "DISPID_WINDOWSETLEFT" << endl; break;
case DISPID_WINDOWSETTOP:
cout << "DISPID_WINDOWSETTOP" << endl; break;
case DISPID_WINDOWSETWIDTH:
cout << "DISPID_WINDOWSETWIDTH" << endl; break;
case DISPID_WINDOWSETHEIGHT:
cout << "DISPID_WINDOWSETHEIGHT" << endl; break;
case DISPID_CLIENTTOHOSTWINDOW:
cout << "DISPID_CLIENTTOHOSTWINDOW" << endl; break;
case DISPID_SETSECURELOCKICON:
cout << "DISPID_SETSECURELOCKICON" << endl; break;
case DISPID_FILEDOWNLOAD:
cout << "DISPID_FILEDOWNLOAD" << endl; break;
case DISPID_NAVIGATEERROR:
cout << "DISPID_NAVIGATEERROR" << endl; break;
case DISPID_PRIVACYIMPACTEDSTATECHANGE:
cout << "DISPID_PRIVACYIMPACTEDSTATECHANGE" << endl; break;
case DISPID_NEWWINDOW3:
cout << "DISPID_NEWWINDOW3" << endl; break;
default:
cout << "????????(" << dispIdMember << ")" << endl; break;
}
// 正常終了
return S_OK;
}
};
/*
ブラウザからのイベントを取得する
*/
int _tmain
(
int argc
, _TCHAR* argv[]
)
{
int iRet = -1;
// COMを初期化する
CoInitialize( NULL );
IWebBrowser2* pIE = NULL;
// IWebBrowser2の取得
CoCreateInstance(
CLSID_InternetExplorer
, NULL
, CLSCTX_LOCAL_SERVER
, IID_IWebBrowser2
, reinterpret_cast<VOID**>( &pIE )
);
// 取得できたかを確認する
if ( NULL != pIE ){
IDispatch* pDisp = NULL;
IConnectionPointContainer* pCPC = NULL;
IConnectionPoint* pCP = NULL;
DWORD dwCookie = 0L;
EventSink_CL *opSink = new EventSink_CL();
if ( NULL != opSink ) {
// IDispatchの取得
if ( S_OK != opSink->QueryInterface( IID_IDispatch
, reinterpret_cast<void**>( &pDisp ) ) ) {
goto err;
}
// 接続ポイントコンテナの取得
if ( S_OK != pIE->QueryInterface( IID_IConnectionPointContainer
, reinterpret_cast<LPVOID*>( &pCPC ) ) ) {
goto err;
}
// 接続ポイント取得
if ( S_OK != pCPC->FindConnectionPoint( DIID_DWebBrowserEvents2, &pCP ) ) {
goto err;
}
// イベントシンクの接続
if ( S_OK != pCP->Advise( reinterpret_cast<IUnknown*>( pDisp ), &dwCookie ) ) {
goto err;
}
}
// 指定したURIをオープン
{
_variant_t vEmpty;
VariantInit( &vEmpty );
// 指定したURIをオープン
pIE->Navigate( _bstr_t( "http://www.wabiapp.com/" )
, &vEmpty, &vEmpty, &vEmpty, &vEmpty );
}
// オープンが完了するまで待つ
{
VARIANT_BOOL bBusy;
do
{
Sleep (500);
// Busy状態の取得
pIE->get_Busy ( &bBusy );
} while ( bBusy );
}
/*
初期状態が非表示となっているので表示する
Navigateを呼び出す前にVisibleにしてもOKです。
*/
pIE->put_Visible( TRUE );
// 入力を待たせる
MessageBox( NULL, L"OKを押すと終了します。", L"メッセージ", MB_OK );
// 正常終了
iRet = 0;
err:
// イベントシンクの接続解除
if ( NULL != pCP && 0 != dwCookie ) pCP->Unadvise( dwCookie );
// I/Fの破棄
SAFE_RELEASE( pCPC );
SAFE_RELEASE( pCP );
SAFE_RELEASE( pDisp );
// イベントシンクの破棄
delete opSink;
// ブラウザを閉じる
if ( NULL != pIE ) pIE->Quit();
}
// IWebBrowser2の解放
SAFE_RELEASE( pIE );
// COMの使用終了
CoUninitialize();
// 正常終了
return( iRet );
}