IEコントロールからのイベントを簡単に受信する

ATLを利用すると比較的簡単にイベントの受信ができる。ここではBEGIN_SINK_MAPによりイベントを受信する方法を紹介する。

まずひな形となるプロジェクトを以下の手順で作成する。

1.Visual Studio 2008の「ファイル」メニューの「新規作成」から「プロジェクト」を選択する。

2.「新しいプロジェクト」ウインドウが開いたら、テンプレートから「ATL/WTLアプリケーションウイザード」を選択してプロジェクトを作成する。

3.「ATL/WTLアプリケーションウイザード」が開いたら「ユーザーインターフェース機能」タブにある「ビューウインドウの形式」で「HTMLページ」を選択して「完了」ボタンを押す。

以上の操作により、シングルドキュメントインターフェースでビューの形式がHTMLページのプロジェクトが自動生成される。



ウイザードにより自動生成されたソースコードのうち、Viewクラスのヘッダーファイルを以下ソースコードのコメントで示したように変更する。
#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などなど、処理したいイベントのシンクマップを追加すればそれだけで処理できるようになる。

プロジェクトファイルをダウンロード

カテゴリー「Internet Explorer」 のエントリー