« 2007年01月 | メイン | 2007年03月 »

前の10件 1  2  3

2007年02月 記事一覧

IEコントロールからのイベントを処理する

test119_01.gif
Internet Explorerのコントロール(IEコントロール)ではスクリプトの実行や画像のダウンロードを抑えるダウンロードコントロール機能や、HTMLファイルの読み込みが終わったことを知らせるための各種イベント機能などを備えている。

ここではIEコントロールでスクリプトの実行などを抑える処理とダウンロード終了などのイベントを取得できるクラス「IDnpIESinkImpl」を作成した。

test119_02.gif
ここではテストのためにATL/WTLアプリケーションウイザードでSDIアプリケーションを作成した。その際にビューウインドウの形式で「HTMLページ」を指定することでビューがIEコントロールになっているウインドウのプロジェクトを作成し、そのIEコントロールからのイベントを処理した。

ビューからIEコントロールを取得するにはQueryControlを利用する。

■自動生成された「プロジェクト名View.h」ファイルの先頭に以下のHTMLイベント処理用のクラスを追加する。自分の好みに応じた処理をしたい場合はこの実装を変える。

#include "DnpIESinkImpl.h"



//
//	イベント処理用クラス
//
class ATL_NO_VTABLE CIESink : 
	public CComObjectRootEx<CComSingleThreadModel>,
	public IOleClientSite,
	public IDispatch,
	public IDnpIESinkImpl
{
public:
	CIESink()
	{
	}

	BEGIN_COM_MAP(CIESink)
		COM_INTERFACE_ENTRY(IDnpIESink)
		COM_INTERFACE_ENTRY(IOleClientSite)
		COM_INTERFACE_ENTRY(IDispatch)
	END_COM_MAP()

	DECLARE_PROTECT_FINAL_CONSTRUCT()


	////////////////////////////
	//	IDispatch;
	//
	STDMETHOD(Invoke)(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr)
	{
		if(dispIdMember == DISPID_AMBIENT_DLCONTROL)
		{
			//ダウンロードコントロール設定

			//ATLTRACE("DISPID_AMBIENT_DLCONTROL\n");
			V_VT(pVarResult) = VT_I4;
			V_I4(pVarResult) = _nAmbientPropertyFlags;
			return	S_OK;
		}


		if(dispIdMember == DISPID_DOWNLOADCOMPLETE)
		{
			ATLTRACE("DISPID_DOWNLOADCOMPLETE\n");
			return	S_OK;
		}
		if(dispIdMember == DISPID_NAVIGATECOMPLETE)
		{
			ATLTRACE("DISPID_NAVIGATECOMPLETE\n");
			return	S_OK;
		}
		if(dispIdMember == DISPID_NAVIGATECOMPLETE2)
		{
			ATLTRACE("DISPID_NAVIGATECOMPLETE2\n");
			return	S_OK;
		}
		if(dispIdMember == DISPID_DOCUMENTCOMPLETE)
		{
			::MessageBox(NULL,_T("HTMLの読み込みが終わりました"),_T(""),MB_OK);
			ATLTRACE("DISPID_DOCUMENTCOMPLETE\n");
			return	S_OK;
		}
		if(dispIdMember == DISPID_NAVIGATEERROR)
		{
			ATLTRACE("DISPID_NAVIGATEERROR\n");
			return	S_OK;
		}

		return	S_OK;
	}
	STDMETHOD(GetTypeInfoCount)(UINT *pctinfo)
	{
		*pctinfo = 0;
		return	S_OK;
	}
	STDMETHOD(GetTypeInfo)(UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo)					{	return	E_NOTIMPL;		}
	STDMETHOD(GetIDsOfNames)(REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId)	{	return	E_NOTIMPL;		}




	///////////////////////////////////
	//	IOleControlSite
	//
	STDMETHOD(GetMoniker)(DWORD dwAssign,DWORD dwWhichMoniker,IMoniker **ppmk)		{	return	E_NOTIMPL;		}
	STDMETHOD(SaveObject)(void)							{	return	E_NOTIMPL;		}
	STDMETHOD(GetContainer)(IOleContainer **ppContainer){	return	E_NOTIMPL;		}
	STDMETHOD(ShowObject)(void)							{	return	E_NOTIMPL;		}
	STDMETHOD(OnShowWindow)(BOOL fShow)					{	return	E_NOTIMPL;		}
	STDMETHOD(RequestNewObjectLayout)(void)				{	return	E_NOTIMPL;		}
};

■ビュークラスの中にIEへのコネクト処理を追加する。この処理を行うことでIEコントロールで発生したイベントを取得できる。ここではウインドウ作成時と破壊時にそれぞれコネクト、ディスコネクトしている

	BEGIN_MSG_MAP(CTest119View)
		MESSAGE_HANDLER(WM_CREATE, OnCreate)
		MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
	END_MSG_MAP()


	CComPtr<IDnpIESink>		_pIESink;


	LRESULT OnCreate(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& /*bHandled*/)
	{
		LRESULT	ret;

		CComPtr<IWebBrowser2>	pIWebBrowser2;

		ret = DefWindowProc(uMsg,wParam,lParam);

		QueryControl(&pIWebBrowser2);

		if(pIWebBrowser2)
		{
			HRESULT	hr;

			_pIESink = new CComObject<CIESink>;

			hr = _pIESink->Init();
			if(SUCCEEDED(hr))
				hr = _pIESink->SetIE(pIWebBrowser2);		//IEのセット
			if(SUCCEEDED(hr))
				hr = _pIESink->Advice();					//接続

			//ダウンロードコントロール設定
			if(SUCCEEDED(hr))
				hr = _pIESink->AmbientPropertyChange(DLCTL_DOWNLOADONLY | DLCTL_NO_SCRIPTS | DLCTL_NO_JAVA | DLCTL_NO_DLACTIVEXCTLS | DLCTL_NO_RUNACTIVEXCTLS);
		}

		return	ret;
	}


	LRESULT OnDestroy(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
	{
		bHandled = FALSE;

		if(_pIESink)
			_pIESink->Init();

		return	0;
	}

■以下のソースコードをファイル名「DnpIESinkImpl.h」として保存する

#pragma	once


#include "mshtml.h"
#include "mshtmdid.h"
#include "Exdisp.h"
#include "Exdispid.h"


//
//	Internet Explorerのイベント処理&ダウンロードコントロール用クラス群
//
//	使用例はこのファイル末尾
//





MIDL_INTERFACE("55647A04-86A4-436d-BF23-154F75582E8A")
IDnpIESink : public IUnknown
{
public:
	STDMETHOD(Init)(void) = 0;
	STDMETHOD(SetIE)(IDispatch* pWebBrowser) = 0;
	STDMETHOD(Advice)(void) = 0;
	STDMETHOD(Unadvice)(void) = 0;
	STDMETHOD(AmbientPropertyChange)(LONG nFlags) = 0;
};




class ATL_NO_VTABLE IDnpIESinkImpl	: public IDnpIESink
{
public:
	IDnpIESinkImpl()
	{
		Init();
	}

	~IDnpIESinkImpl()
	{
		ATLASSERT(_pConnectionPoint == NULL);		//接続が解除されていない!
		Init();
	}

protected:
	DWORD		_dwCookie;
	LONG		_nAmbientPropertyFlags;
	CComPtr<IWebBrowser2>		_pWebBrowser2;
	CComPtr<IConnectionPoint>	_pConnectionPoint;

public:


	//
	//	クラスの初期化
	//
	STDMETHOD(Init)(void)
	{
		_nAmbientPropertyFlags = 0;

		if(_pConnectionPoint)
			Unadvice();

		if(_pWebBrowser2)
			_pWebBrowser2 = NULL;

		_dwCookie = 0;

		return	S_OK;
	}



	//
	//	Internet Explorerの設定
	//
	STDMETHOD(SetIE)(IDispatch* pWebBrowser)
	{
		ATLASSERT(pWebBrowser);
		if(pWebBrowser == NULL)
			return	E_FAIL;

		ATLASSERT(_pWebBrowser2 == NULL);
		if(_pWebBrowser2)
			return	E_FAIL;

		return	pWebBrowser->QueryInterface(IID_IWebBrowser2,(void**)&_pWebBrowser2);
	}



	//
	//	Internet Explorerとの接続
	//
	//	必ずUnadviceすること!
	//
	STDMETHOD(Advice)(void)
	{
		HRESULT	hr;

		CComPtr<IUnknown>	pUnknown;
		CComPtr<IConnectionPointContainer>	pConnectionPointContainer;

		ATLASSERT(_pConnectionPoint == NULL);		//接続済み
		ATLASSERT(_pWebBrowser2);
		if(_pWebBrowser2 == NULL)
			return	E_FAIL;


		QueryInterface(IID_IUnknown,(void**)&pUnknown);

		hr = E_FAIL;
		_dwCookie = 0;
		_pWebBrowser2->QueryInterface(&pConnectionPointContainer);
		if(pConnectionPointContainer)
		{
			_pConnectionPoint = NULL;
			pConnectionPointContainer->FindConnectionPoint(__uuidof(DWebBrowserEvents2),&_pConnectionPoint);
		}
		if(_pConnectionPoint)
			hr = _pConnectionPoint->Advise(pUnknown,&_dwCookie);

		return	hr;
	}



	//
	//	Internet Explorerとの接続解除
	//
	STDMETHOD(Unadvice)(void)
	{
		HRESULT	hr;

		if(_pConnectionPoint == NULL)
			return	E_FAIL;

		hr = _pConnectionPoint->Unadvise(_dwCookie);
		if(SUCCEEDED(hr))
		{
			_dwCookie = 0;
			_pConnectionPoint = NULL;
			return	S_OK;
		}

		return	E_FAIL;
	}



	//
	//	ダウンロードコントロールの設定
	//
	//
	//	nFlagsは以下のようなフラグ
	//		DLCTL_DOWNLOADONLY | DLCTL_NO_SCRIPTS | DLCTL_NO_JAVA | DLCTL_NO_DLACTIVEXCTLS | DLCTL_NO_RUNACTIVEXCTLS;
	//
	STDMETHOD(AmbientPropertyChange)(LONG nFlags)
	{
		HRESULT	hr;

		CComPtr<IOleControl>	pOleControl;
		CComPtr<IOleObject>		pOleObject;
		CComPtr<IOleClientSite>	pOleClientSite;

		hr = QueryInterface(IID_IOleClientSite,(void**)&pOleClientSite);
		if(pOleClientSite == NULL)
			return	E_FAIL;

		if(_pWebBrowser2 == NULL)
			return	E_FAIL;

		hr = _pWebBrowser2->QueryInterface(&pOleObject);
		if(pOleObject)
			hr = pOleObject->SetClientSite(pOleClientSite);

		if(SUCCEEDED(hr))
			hr = _pWebBrowser2->QueryInterface(&pOleControl);
		if(pOleControl)
		{
			_nAmbientPropertyFlags = nFlags;
			hr = pOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_DLCONTROL);
		}

		return	hr;
	}
};









//
//	使用例
//


//
////	イベント処理用クラス
////
//class ATL_NO_VTABLE CIESink : 
//	public CComObjectRootEx<CComSingleThreadModel>,
//	public IOleClientSite,
//	public IDispatch,
//	public IDnpIESinkImpl
//{
//public:
//	CIESink()
//	{
//	}
//
//	BEGIN_COM_MAP(CIESink)
//		COM_INTERFACE_ENTRY(IDnpIESink)
//		COM_INTERFACE_ENTRY(IOleClientSite)
//		COM_INTERFACE_ENTRY(IDispatch)
//	END_COM_MAP()
//
//	DECLARE_PROTECT_FINAL_CONSTRUCT()
//
//
//	////////////////////////////
//	//	IDispatch;
//	//
//	STDMETHOD(Invoke)(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,DISPPARAMS *pDispParams,VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr)
//	{
//		if(dispIdMember == DISPID_AMBIENT_DLCONTROL)
//		{
//			//ダウンロードコントロール設定
//
//			//ATLTRACE("DISPID_AMBIENT_DLCONTROL\n");
//			V_VT(pVarResult) = VT_I4;
//			V_I4(pVarResult) = _nAmbientPropertyFlags;
//			return	S_OK;
//		}
//
//
//		if(dispIdMember == DISPID_DOWNLOADCOMPLETE)
//		{
//			ATLTRACE("DISPID_DOWNLOADCOMPLETE\n");
//			return	S_OK;
//		}
//		if(dispIdMember == DISPID_NAVIGATECOMPLETE)
//		{
//			ATLTRACE("DISPID_NAVIGATECOMPLETE\n");
//			return	S_OK;
//		}
//		if(dispIdMember == DISPID_NAVIGATECOMPLETE2)
//		{
//			ATLTRACE("DISPID_NAVIGATECOMPLETE2\n");
//			return	S_OK;
//		}
//		if(dispIdMember == DISPID_DOCUMENTCOMPLETE)
//		{
//			ATLTRACE("DISPID_DOCUMENTCOMPLETE\n");
//			return	S_OK;
//		}
//		if(dispIdMember == DISPID_NAVIGATEERROR)
//		{
//			ATLTRACE("DISPID_NAVIGATEERROR\n");
//			return	S_OK;
//		}
//
//		return	S_OK;
//	}
//	STDMETHOD(GetTypeInfoCount)(UINT *pctinfo)
//	{
//		*pctinfo = 0;
//		return	S_OK;
//	}
//	STDMETHOD(GetTypeInfo)(UINT iTInfo,LCID lcid,ITypeInfo **ppTInfo)					{	return	E_NOTIMPL;		}
//	STDMETHOD(GetIDsOfNames)(REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId)	{	return	E_NOTIMPL;		}
//
//
//
//
//	///////////////////////////////////
//	//	IOleControlSite
//	//
//	STDMETHOD(GetMoniker)(DWORD dwAssign,DWORD dwWhichMoniker,IMoniker **ppmk)		{	return	E_NOTIMPL;		}
//	STDMETHOD(SaveObject)(void)							{	return	E_NOTIMPL;		}
//	STDMETHOD(GetContainer)(IOleContainer **ppContainer){	return	E_NOTIMPL;		}
//	STDMETHOD(ShowObject)(void)							{	return	E_NOTIMPL;		}
//	STDMETHOD(OnShowWindow)(BOOL fShow)					{	return	E_NOTIMPL;		}
//	STDMETHOD(RequestNewObjectLayout)(void)				{	return	E_NOTIMPL;		}
//};
//
//



////
////	ウインドウ内での使用
////
//class	CTestDlg : public CDialog
//{
//	CComPtr<IDnpIESink>		_pIESink;
//
//public:
//	(...)
//
//	~CTestDlg()
//	{
//		if(_pIESink)
//			_pIESink->Init();
//	}
//
//
//	BOOL	OnInitDialog(...)
//	{
//		(...)
//
//		HRESULT	hr;
//
//		_pIESink = new CComObject<CIESink>;
//
//		hr = _pIESink->Init();
//		if(SUCCEEDED(hr))
//			hr = _pIESink->SetIE(pWebBrowser2);			//IEのセット
//		if(SUCCEEDED(hr))
//			hr = _pIESink->Advice();					//接続
//
//		//ダウンロードコントロール設定
//		if(SUCCEEDED(hr))
//			hr = _pIESink->AmbientPropertyChange(DLCTL_DOWNLOADONLY | DLCTL_NO_SCRIPTS | DLCTL_NO_JAVA | DLCTL_NO_DLACTIVEXCTLS | DLCTL_NO_RUNACTIVEXCTLS);
//
//		(...)
//
//		return	TRUE;
//	}
//
//	(...)
//};


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

int型の数値を文字列に変換するのにitoa関数は利用できない

test120.gif
int型の数値を文字列に変換するには、従来からのC/C++ではitoa関数を利用した。しかしWindowsプログラミングではitoa関数は使わない方がいい。

もちろんitoa関数も使えるが文字列バッファーサイズを指定できるためセキュリティが若干高い_itoa_s系の関数を利用した方がいい。さらに言うと実際のプログラミングでは速度的には劣るがバッファーのことを考える必要がなくコーディングが楽なCString型の文字列を利用する変換がいいだろう。



bool	Test()
{
	////////////////////////////////
	//	int型数値を文字列に変換
	//
	{
		//char型文字列に変換
		int		nValue = 123;
		char	pszText[256];

		//itoaや_itoaは利用しない方がいい!代わりに_itoa_sを使う
		::_itoa_s(nValue,pszText,256 * sizeof(char),10);

		::MessageBoxA(NULL,pszText,"",MB_OK);
	}
	{
		//wchar_t型文字列に変換
		int		nValue = 123;
		wchar_t	pszText[256];

		//_itowは利用しない方がいい!代わりに_itow_sを使う
		::_itow_s(nValue,pszText,256 * sizeof(wchar_t),10);

		::MessageBoxW(NULL,pszText,L"",MB_OK);
	}
	{
		//TCHAR型文字列に変換
		int		nValue = 123;
		TCHAR	pszText[256];

		//_itotは利用しない方がいい!代わりに_itot_sを使う
		::_itot_s(nValue,pszText,256 * sizeof(TCHAR),10);

		::MessageBox(NULL,pszText,_T(""),MB_OK);
	}
	{
		//CString型文字列に変換
		int		nValue = 123;
		CString	strText;

		strText.Format(_T("%d"),nValue);

		::MessageBox(NULL,strText,_T(""),MB_OK);
	}

	return	true;
}


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

int型の数値を16進数表記の文字列に変換する

test121.gif
int型の数値を16進数の文字列に変換するには、従来からのC/C++ではitoa関数もしくはsprintf関数を利用した。しかしWindowsプログラミングではitoa関数などは使わない方がいい。

もちろんitoa関数も使えるが文字列バッファーサイズを指定できるためセキュリティが若干高い_itoa_s系の関数を利用した方がいい。さらに言うと実際のプログラミングでは速度的には劣るがバッファーのことを考える必要がなくコーディングが楽なCString型の文字列を利用する変換がいいだろう。

_itoa_s系の関数の場合は第4引数に「16」を指定することで16進数の文字列を取得できる。



bool	Test()
{
	////////////////////////////////
	//	int型数値を16進数文字列に変換
	//
	{
		//char型文字列に変換
		int		nValue = 123;
		char	pszText[256];

		//itoaや_itoaは利用しない方がいい!代わりに_itoa_sを使う
		::_itoa_s(nValue,pszText,256 * sizeof(char),16);

		::MessageBoxA(NULL,pszText,"",MB_OK);
	}
	{
		//wchar_t型文字列に変換
		int		nValue = 123;
		wchar_t	pszText[256];

		//_itowは利用しない方がいい!代わりに_itow_sを使う
		::_itow_s(nValue,pszText,256 * sizeof(wchar_t),16);

		::MessageBoxW(NULL,pszText,L"",MB_OK);
	}
	{
		//TCHAR型文字列に変換
		int		nValue = 123;
		TCHAR	pszText[256];

		//_itotは利用しない方がいい!代わりに_itot_sを使う
		::_itot_s(nValue,pszText,256 * sizeof(TCHAR),16);

		::MessageBox(NULL,pszText,_T(""),MB_OK);
	}
	{
		//CString型文字列に変換
		int		nValue = 123;
		CString	strText;

		//小文字の16進数
		strText.Format(_T("%x"),nValue);
		::MessageBox(NULL,strText,_T(""),MB_OK);

		//大文字の16進数
		strText.Format(_T("%X"),nValue);
		::MessageBox(NULL,strText,_T(""),MB_OK);
	}

	return	true;
}


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

10進数表記の文字列をint型の数値に変換する

文字列をint型の数値に変換するには従来通りatoi系の関数が利用できる。変換元の文字列の型に応じてatoi、_wtoi、_ttoiを使い分けるといい。

bool	Test()
{
	////////////////////////////////
	//	10進数表記の文字列をint型数値に変換
	//
	{
		//char型文字列から変換
		int		nValue;
		char	pszText[] = "123";

		nValue = ::atoi(pszText);
	}
	{
		//wchar_t型文字列から変換
		int		nValue;
		wchar_t	pszText[] = L"123";

		nValue = ::_wtoi(pszText);
	}
	{
		//TCHAR型文字列から変換
		int		nValue;
		TCHAR	pszText[] = _T("123");

		nValue = ::_ttoi(pszText);
	}
	{
		//CString型文字列から変換
		int		nValue;
		CString	strText = _T("123");

		nValue = ::_ttoi(strText);
	}

	return	true;
}

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

16進数表記の文字列をlong型の数値に変換する

「0x0123」や「0FFF」のように16進数で書かれた文字列を数値に変換するにはstrtol系の関数が利用できる。従来通りに1文字ずつ判別しながら数値に変換してもいいが、この関数を利用すればかなり楽ができる。覚えておいて損はないだろう。

bool	Test()
{
	////////////////////////////////
	//	16進数表記の文字列をlong型の数値に変換
	//
	{
		//char型文字列から変換
		long	nValue;
		char	pszText[] = "0ab3";
		char*	pszEnd;

		nValue = ::strtol(pszText,&pszEnd,16);
	}
	{
		//wchar_t型文字列から変換
		long		nValue;
		wchar_t		pszText[] = L"0ab3";
		wchar_t*	pszEnd;

		nValue = ::wcstol(pszText,&pszEnd,16);
	}
	{
		//TCHAR型文字列から変換
		long	nValue;
		TCHAR	pszText[] = _T("0ab3");
		TCHAR*	pszEnd;

		nValue = ::_tcstol(pszText,&pszEnd,16);
	}
	{
		//CString型文字列から変換
		long	nValue;
		CString	strText = _T("0ab3");
		TCHAR*	pszEnd;

		nValue = ::_tcstol(strText,&pszEnd,16);
	}

	return	true;
}

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

2進数表記の文字列をlong型の数値に変換する

「01001001」のように0と1だけの2進数で書かれた文字列を数値に変換するにはstrtol系の関数が利用できる。従来通りに1文字ずつ判別しながら数値に変換してもいいが、この関数を利用すればかなり楽ができる。覚えておいて損はないだろう。

bool	Test()
{
	////////////////////////////////
	//	2進数表記の文字列をlong型の数値に変換
	//
	{
		//char型文字列から変換
		long	nValue;
		char	pszText[] = "01001001";
		char*	pszEnd;

		nValue = ::strtol(pszText,&pszEnd,2);
	}
	{
		//wchar_t型文字列から変換
		long		nValue;
		wchar_t		pszText[] = L"01001001";
		wchar_t*	pszEnd;

		nValue = ::wcstol(pszText,&pszEnd,2);
	}
	{
		//TCHAR型文字列から変換
		long	nValue;
		TCHAR	pszText[] = _T("01001001");
		TCHAR*	pszEnd;

		nValue = ::_tcstol(pszText,&pszEnd,2);
	}
	{
		//CString型文字列から変換
		long	nValue;
		CString	strText = _T("01001001");
		TCHAR*	pszEnd;

		nValue = ::_tcstol(strText,&pszEnd,2);
	}

	return	true;
}

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

前の10件 1  2  3





usefullcode@gmail.com

About 2007年02月

2007年02月にブログ「UsefullCode.net」に投稿されたすべてのエントリーです。

前の記事は2007年01月です。

次の記事は2007年03月です。

他にも多くのエントリーがあります。メインページ記事一覧も見てください。