第34回 ステータスバーのダブルクリックでスクリプトエラーの詳細情報を表示する (タブブラウザーを作る)

tabbrowser137.gif
前回は開いているページでスクリプトエラーが発生したときにステータスバーにアイコンが表示されるようにした。今回はステータスバーをダブルクリックしたときにエラーに関する情報を表示する。

IEコントロールでは私の知る限りエラーメッセージを後から表示するための機能は備わっていない。Internet Explorer 8などではエラーメッセージを内部で保管しておき、必要に応じてエラー情報をダイアログで表示していると思われる。

そのため今回は内部でエラー情報を保持してステータスバーがダブルクリックされた時にそれを表示することにする。まずスクリプトエラー検出用のインターフェースにエラーメッセージを表示するためのメソッドを追加する。
//スクリプトエラーの通知先ウインドウなどを設定するためのインターフェース
MIDL_INTERFACE("2C66181A-27D5-486e-A84A-3B8EDAE1951F")
IScriptErrorSetting : public IUnknown
{
public:
	STDMETHOD (put_hWndNotify)(HWND hWnd) = 0;		//エラーの通知先HWND(ビューのHWND)を指定
	STDMETHOD (ShowLastScriptError)(HWND hWnd) = 0;		//■追加
};

	CAtlString		_strErrorMessage;		//■追加 表示用のエラー情報

	//■追加
	STDMETHOD (ShowLastScriptError)(HWND hWnd)
	{
		if(_strErrorMessage == _T(""))
			return	E_FAIL;

		::MessageBox(hWnd,_strErrorMessage,_T("エラー情報"),MB_OK | MB_ICONWARNING);

		return	S_OK;
	}

tabbrowser138.gif そしてExecでスクリプトエラーを検出したら、その詳細情報を保存しておく。
    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;		//エラーを無視してスクリプト続行

			if(_hWndNotify && ::IsWindow(_hWndNotify))
				::SendMessage(_hWndNotify,WM_DNP_SCRIPTERROR,(WPARAM)TRUE,NULL);


			//■追加
			//エラー情報を保存
			//面倒なので表示用に整形して_strErrorMessageに代入している
			//本当はURIをチェックして同じならどんどん貯めておいた方がいい
			{
				_strErrorMessage = _T("");

				CComPtr<IHTMLDocument2>	pIHTMLDocument2;
				CComPtr<IHTMLWindow2>	pIHTMLWindow2;
				CComPtr<IHTMLEventObj>	pIHTMLEventObj;

				if(pvaIn && pvaIn->punkVal)
					pvaIn->punkVal->QueryInterface(IID_IHTMLDocument2,(void**)&pIHTMLDocument2);
				if(pIHTMLDocument2)
					pIHTMLDocument2->get_parentWindow(&pIHTMLWindow2);
				if(pIHTMLWindow2)
					pIHTMLWindow2->get_event(&pIHTMLEventObj);
				if(pIHTMLEventObj)
				{
					int			i;
					OLECHAR*	pwszName[] = {L"errorLine",L"errorCharacter",L"errorCode",L"errorMessage",L"errorUrl"};
					TCHAR*		pszHeader[] = {_T("ライン:"),_T("文字:"),_T("エラーコード:"),_T(""),_T("URI:")};

					for(i = 0; i < 5; i++)
					{
						DISPID		nDispID;
						HRESULT		hr;
						DISPPARAMS	sDispParams;
						CComVariant	vResult;

						//エラー情報のDISPID取得
						hr = pIHTMLEventObj->GetIDsOfNames(IID_NULL,&pwszName[i],1,LOCALE_SYSTEM_DEFAULT,&nDispID);
						if(FAILED(hr))
							continue;

						//エラー情報取得
						::ZeroMemory(&sDispParams,sizeof(DISPPARAMS));
						hr = pIHTMLEventObj->Invoke(nDispID,IID_NULL,LOCALE_SYSTEM_DEFAULT,DISPATCH_PROPERTYGET,&sDispParams,&vResult,NULL,NULL);
						if(FAILED(hr))
							continue;

						CAtlString	strBuff(vResult);

						_strErrorMessage += pszHeader[i];
						_strErrorMessage += strBuff;
						_strErrorMessage += _T("\n");
					}
				}
			}

			return S_OK;
		}

		return E_NOTIMPL;
    }

tabbrowser139.gif ビュークラスの中に上で最初に実装したスクリプトエラーを表示するための関数を用意する。
	//■追加
	bool	ShowScriptError(void)
	{
		if(_bPageError == false)
			return	false;			//現在エラー中ではない

		CComPtr<IScriptErrorSetting>	pIScriptErrorSetting;	//独自に作ったインターフェース

		if(_pHideScriptError)
			_pHideScriptError->QueryInterface(&pIScriptErrorSetting);
		if(pIScriptErrorSetting)
			pIScriptErrorSetting->ShowLastScriptError(m_hWnd);		//エラーメッセージの表示

		return	true;
	}

tabbrowser140.gif
最後にメインウインドウにステータスバーがダブルクリックされたときの処理を追加する。

ステータスバーがダブルクリックされるとメインウインドウにWM_NOTIFYが届くので、今回はそれを処理することにした。
		COMMAND_ID_HANDLER(ID_IE_ORGANIZE_FAVORITE, OnIEOrganizeFavorite)
		NOTIFY_CODE_HANDLER(TBVN_CONTEXTMENU, OnTabContextMenu)
		NOTIFY_CODE_HANDLER(TBVN_PAGEACTIVATED, OnTabPageActivated)
		NOTIFY_HANDLER(ATL_IDW_STATUS_BAR, NM_DBLCLK, OnStatusBarDblClk)			//■追加
		MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
		MESSAGE_HANDLER(WM_SIZE, OnSize)
		COMMAND_RANGE_HANDLER(ID_FAVORITE_FIRST,ID_FAVORITE_LAST,OnFavorite)
		CHAIN_MSG_MAP_MEMBER(_cFovMenu)
		CHAIN_MSG_MAP(CUpdateUI<CMainFrame>)
		CHAIN_MSG_MAP(CFrameWindowImpl<CMainFrame>)
	END_MSG_MAP()



	//■追加
	//ステータスバーのダブルクリック処理
	LRESULT OnStatusBarDblClk(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
	{
		bHandled = FALSE;

		NMMOUSE*	pNmMouse = (NMMOUSE*)pnmh;
		CTabBrowser100View*	pView;

		if(pNmMouse == NULL)
			return	0;

		if(pNmMouse->dwItemSpec == 0)
		{
			//ゼロ番目のペインがダブルクリックされた
			pView = GetActivePageView();
			if(pView)
				pView->ShowScriptError();			//スクリプトエラー情報を表示する
		}

		return	0;
	}

tabbrowser141.gif
これでビルド/実行するとスクリプトエラー発生時にステータスバーをダブルクリックすることでエラーの詳細表示を見れるようになった。

次回はメニューバーにInternet Explorerにあるような項目を追加する。

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


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