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 ); }