ATLを利用すると比較的簡単にイベントの受信ができる。ここではBEGIN_SINK_MAPによりイベントを受信する方法を紹介する。
まずひな形となるプロジェクトを以下の手順で作成する。
1.Visual Studio 2008の「ファイル」メニューの「新規作成」から「プロジェクト」を選択する。
2.「新しいプロジェクト」ウインドウが開いたら、テンプレートから「ATL/WTLアプリケーションウイザード」を選択してプロジェクトを作成する。
3.「ATL/WTLアプリケーションウイザード」が開いたら「ユーザーインターフェース機能」タブにある「ビューウインドウの形式」で「HTMLページ」を選択して「完了」ボタンを押す。
以上の操作により、シングルドキュメントインターフェースでビューの形式がHTMLページのプロジェクトが自動生成される。
#pragma once
//■以下の宣言を5行追加
#define SINKID_COMTESTEVENTS 0 //Viewとして使うだけならいちいちdefineしなくてもいいが。。。
#include "mshtml.h"
#include "mshtmdid.h"
#include "Exdisp.h"
#include "Exdispid.h"
class CMy20090318_htmleventView : public CWindowImpl<CMy20090318_htmleventView, CAxWindow>
,public IDispEventImpl<SINKID_COMTESTEVENTS, CMy20090318_htmleventView, &DIID_DWebBrowserEvents2> //■この行を追加
{
CComPtr<IWebBrowser2> _pIWebBrowser2; //■この行を追加。このビューがホストしているIWebBrowser2を使いやすいようにメンバーとして用意する
public:
DECLARE_WND_SUPERCLASS(NULL, CAxWindow::GetWndClassName())
BOOL PreTranslateMessage(MSG* pMsg)
{
if((pMsg->message < WM_KEYFIRST || pMsg->message > WM_KEYLAST) &&
(pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST))
return FALSE;
// このメッセージを翻訳する機会をHTML ページに与える
return (BOOL)SendMessage(WM_FORWARDMSG, 0, (LPARAM)pMsg);
}
//■以下の3行を追加(IEコントロールのイベントマップ。ここではDISPID_DOCUMENTCOMPLETEのみ処理している)
BEGIN_SINK_MAP(CMy20090318_htmleventView)
SINK_ENTRY_EX(SINKID_COMTESTEVENTS, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
END_SINK_MAP()
BEGIN_MSG_MAP(CMy20090318_htmleventView)
MESSAGE_HANDLER(WM_CREATE, OnCreate) //■WM_CREATEのメッセージハンドラを追加
MESSAGE_HANDLER(WM_DESTROY, OnDestroy) //■WM_DESTROYのメッセージハンドラを追加
END_MSG_MAP()
///////////////////////////////////////////////////////
//■これ以降の3つの関数を追加
//
//
// IEコントロールのイベントによりHTMLページの読み込みが終わった時に呼ばれる
//
STDMETHOD(OnDocumentComplete)(IDispatch* pDisp, VARIANT* URL)
{
ATLTRACE("■OnDocumentComplete Received.\n");
return S_OK;
}
LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
LRESULT ret;
//IWebBrowser2はOnCreate後でないと取得できないのでDefWindowProcで先に生成してしまう
ret = DefWindowProc(uMsg,wParam,lParam);
//IWebBroser2の取得
_pIWebBrowser2 = NULL;
QueryControl(&_pIWebBrowser2);
if(_pIWebBrowser2 == NULL)
return ret;
HRESULT hr;
CComVariant vEmpty;
//IEコントロールへの接続。これによりイベントが受信できるようになる。
hr = Advise(_pIWebBrowser2);
//URLの読み込み
vEmpty.Clear();
hr = _pIWebBrowser2->Navigate(L"http://www.usefullcode.net/",&vEmpty,&vEmpty,&vEmpty,&vEmpty);
return ret;
}
LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
{
bHandled = FALSE;
if(_pIWebBrowser2)
{
//IEコントロールからの切断
Unadvise(_pIWebBrowser2);
_pIWebBrowser2 = NULL;
}
return 0;
}
};
たったこれだけの手順でIEコントロールからのDISPID_DOCUMENTCOMPLETEを処理できる。BEGIN_SINK_MAP内にDISPID_BEFORENAVIGATE2やDISPID_NAVIGATECOMPLETE2などなど、処理したいイベントのシンクマップを追加すればそれだけで処理できるようになる。
プロジェクトファイルをダウンロード
