第28回 スクリプトエラーダイアログが表示されないようにする (タブブラウザーを作る)

tabbrowser109.gif
今回は前に紹介した「IEコントロールのスクリプトエラー表示を消す」の方法を用いて、javascriptなどにエラーがあってもエラーダイアログが表示されないようにする。

まず、前に作成したクラスをタブブラウザーのプロジェクトに取り込む。「プロジェクト」メニューから「既存項目の追加」を選択する。

tabbrowser110.gif
そして「DnpDocHostUIHandlerImpl.h」をプロジェクトに追加する。

tabbrowser112.gif 前はWTLのアプリケーションウイザードが生成したビュークラスにIDocHostUIHandlerなどを追加することでスクリプトエラーを消した。しかし今回は将来的な拡張のことも考慮して、独立したクラスCHideScriptError を作りそこでエラーダイアログを非表示にすることにした。
#include "DnpDocHostUIHandlerImpl.h"		//■追加

//■追加
//スクリプトエラーを消すためのUIHandler
class CHideScriptError :
	public CComObjectRootEx<CComSingleThreadModel>
	,public IDnpDocHostUIHandlerImpl
	,public	IDispatchImpl<IDispatch>
	,public IOleCommandTarget
{
public:

	BEGIN_COM_MAP(CHideScriptError)
		COM_INTERFACE_ENTRY(IDispatch)
		COM_INTERFACE_ENTRY(IDocHostUIHandler)
		COM_INTERFACE_ENTRY(IOleCommandTarget)
	END_COM_MAP()


    STDMETHODIMP QueryStatus( const GUID* pguidCmdGroup, ULONG cCmds, OLECMD prgCmds[], OLECMDTEXT* pCmdText ) 
	{
		return E_NOTIMPL; 
    }

    STDMETHODIMP Exec( const GUID* pguidCmdGroup, DWORD nCmdID, DWORD nCmdExecOpt, VARIANTARG* pvaIn, VARIANTARG* pvaOut)
    {
		//コマンドがスクリプトエラーを示すものなら、エラー表示を無効にする
		if(nCmdID == OLECMDID_SHOWSCRIPTERROR)
		{
			(*pvaOut).vt		= VT_BOOL;
			(*pvaOut).boolVal	= VARIANT_TRUE;
			return S_OK;
		}

		return E_NOTIMPL;
    }
};

tabbrowser113.gif そしてビュークラス内でIEコントロールのUIHandlerとしてCHideScriptError を渡す。
	CComPtr<IDocHostUIHandler>		_pHideScriptError;		//■追加


	//■追加
	//UIHandlerの変更。本当はもともと入っていたUIhandlerを取得/保持してそれも併せて使うようにすべき
	bool	ChangeUIHandler(void)
	{
		HRESULT	hr = E_FAIL;

		CComPtr<IDispatch>	pIDispatch;
		CComPtr<ICustomDoc>	pICustomDoc;

		if(_pHideScriptError == NULL)
			_pHideScriptError = new CComObject<CHideScriptError>;

		if(_pIWebBrowser2)
			hr = _pIWebBrowser2->get_Document(&pIDispatch);
		if(pIDispatch)
			hr = pIDispatch->QueryInterface(IID_ICustomDoc,(void **)&pICustomDoc);
		if(pICustomDoc)
			hr = pICustomDoc->SetUIHandler(_pHideScriptError);

		return	SUCCEEDED(hr) ? true : false;
	}

	//HTMLページが読み終わったときに呼ばれる処理
	void	_stdcall OnDocumentComplete(IDispatch* pDisp, VARIANT* vURL)
	{
		if(pDisp != _pIWebBrowser2)
			return;			//フレームなどの読み込み終了は無視

		ChangeUIHandler();			//■追加 UIHandlerを変更する

		HICON		hIcon;
		CAtlString	strFile;

		//テンポラリファイルパス取得
		{
			DWORD	dwRet;
			TCHAR	pszPath[MAX_PATH + 1024];
			TCHAR	pszFile[MAX_PATH + 1024];

			dwRet = ::GetTempPath(MAX_PATH + 1024,pszPath);				//テンポラリフォルダ取得
			if(dwRet)
				dwRet = ::GetTempFileName(pszPath,NULL,0,pszFile);		//テンポラリファイル名自動生成
			if(dwRet)
				strFile = pszFile;
			if(strFile == _T(""))
				return;
		}

		//インターネットショートカットファイル作成
		{
			bool	ret;

			strFile += _T(".url");
			ret = CreateInternetShortcut((CAtlString)vURL->bstrVal,strFile);
			if(ret == false)
				return;

			//インターネットショートカットにアイコンが適用されるのを待つ(//■■これだとダメ?要調査)
			::SHChangeNotify(SHCNE_CREATE,SHCNF_PATH | SHCNF_FLUSH,(LPCTSTR)strFile,NULL);
		}

		//ファイルからHICONを取得
		{
			SHFILEINFO	sShFileInfo;
			HIMAGELIST	hImageList;

			//パスからアイコン取得
			hImageList = (HIMAGELIST)::SHGetFileInfo(strFile,0,&sShFileInfo,sizeof(SHFILEINFO),SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
			hIcon = ::ImageList_GetIcon(hImageList,sShFileInfo.iIcon,ILD_NORMAL);
			::ImageList_Destroy(hImageList);
		}
		::remove((CAtlStringA)strFile);		//ファイル削除
		if(hIcon == NULL)
			return;

		//タブにHICONを割り当てる
		{
			int			nPage;
			int			nImage;
			CImageList	cImageList;

			nPage = _pTabView->PageIndexFromHwnd(m_hWnd);
			cImageList = _pTabView->GetImageList();			//タブのイメージリスト取得

			nImage = _pTabView->GetPageImage(nPage);		//現在のイメージ番号取得
			if(nImage < 0)
			{
				//タブに画像がなければ新しく追加して使う
				nImage = cImageList.AddIcon(hIcon);
			}
			else
			{
				//タブに画像があればそれと置き換える
				cImageList.ReplaceIcon(nImage,hIcon);
			}
			_pTabView->SetPageImage(nPage,nImage);		//nImageが変わらなくても再描画のためにセットしなおす
		}
		::DestroyIcon(hIcon);
	}

tabbrowser114.gif 今回作成しているタブブラウザーでは「Googleツールバー」の機能を実装している。このツールバーが独自にUIHandlerを横取りしているようなので、タブが切り替わったときにUIhandlerを上書きしておく。
	//タブの選択変更があったときメインウインドウから呼ばれる
	bool	OnTabPageChange(bool bActivated)
	{
		if(_pIDeskBand == NULL)
			return	false;

		if(bActivated)
			_pIDeskBand->ShowDW(TRUE);		//IEツールバーを表示
		else
			_pIDeskBand->ShowDW(FALSE);		//IEツールバーを消す

		//■追加
		//GoogleツールバーはShowDWで?UIハンドラーを変更するのでここで上書き。
		//ShowWindowで表示/非表示を切り替えれば解決するのかな?要調査
		if(bActivated)
			ChangeUIHandler();			//UIHandlerを変更する

		return	true;
	}

tabbrowser111.gif
これでビルド/実行すると、そのページにエラーがあってもエラーダイアログがでなくなった。

しかし逆にエラーがあってもユーザーにはエラーがあったことが分からなくなってしまった。次回はユーザーが分かるようにエラーがあった場合には通知する処理を追加する。


※ちなみに「このリンク」をクリックするとスクリプトエラーが発生する。

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


カテゴリー「タブブラウザーを作る」 のエントリー