前の10件 10  11  12  13  14  15  16  17  18  19  20

記事一覧

第44回 セキュリティレポートを表示する (タブブラウザーを作る)

tabbrowser182.gif
前回はステータスバーのダブルクリックによりプライバシーレポートが表示されるようにした。

今回はセキュリティレポートの表示を行う。セキュリティレポート用にダブルクリック処理などは前回すでに用意したので実装が必要なのは実際に表示する部分だけとなる。

セキュリティレポートはwininet.dllからエクスポートされているInternetShowSecurityInfoByURLWもしくはInternetShowSecurityInfoByURLAにURLを指定して呼び出すことで表示される。
	//■処理変更
	bool	ShowSecurityReport(HWND hWnd)
	{
		HRESULT		hr;
		CComBSTR	bstrURL;

		if(_pIWebBrowser2 == NULL)
			return	false;

		//URL取得
		hr = _pIWebBrowser2->get_LocationURL(&bstrURL);
		if(FAILED(hr))
			return	false;

		return	ShowSecurityReport(hWnd,(CAtlString)bstrURL);
	}


	//■追加
	bool	ShowSecurityReport(HWND hWnd,LPCTSTR pszURL)
	{
		bool		ret;
		HMODULE		hDLL;

		BOOL (WINAPI* pfnInternetShowSecurityInfoByURLW)(const WCHAR*,HWND);
		BOOL (WINAPI* pfnInternetShowSecurityInfoByURLA)(const char*,HWND);

		if(pszURL == NULL)
			return	false;

		hDLL = ::LoadLibrary(_T("wininet.dll"));
		if(hDLL == NULL)
			return	false;

		ret = false;
		(FARPROC&)pfnInternetShowSecurityInfoByURLW = ::GetProcAddress(hDLL,"InternetShowSecurityInfoByURLW");
		if(pfnInternetShowSecurityInfoByURLW)
		{
	#ifdef	_UNICODE
			pfnInternetShowSecurityInfoByURLW(pszURL,hWnd);
	#else
			CAtlStringW	ustrURL;
			ustrURL = pszURL;
			pfnInternetShowSecurityInfoByURLW(ustrURL.GetBuffer(0),hWnd);
	#endif
			ret = true;
		}

		if(ret == false)
		{
			(FARPROC&)pfnInternetShowSecurityInfoByURLA = ::GetProcAddress(hDLL,"InternetShowSecurityInfoByURLA");
			if(pfnInternetShowSecurityInfoByURLA)
			{
	#ifdef	_UNICODE
				CAtlStringA	strBuff;
				strBuff = pszURL;
				pfnInternetShowSecurityInfoByURLA(strBuff.GetBuffer(0),hWnd);
	#else
				pfnInternetShowSecurityInfoByURLA(pszURL,hWnd);
	#endif
				ret = true;
			}
		}

		::FreeLibrary(hDLL);

		return	ret;
	}

tabbrowser183.gif
これでステータスバーのセキュリティレポート用のペインをダブルクリックすることでセキュリティレポートが表示されるようになった。

次回はプライバシー状態やセキュリティ状態に応じてステータスバーにアイコンが表示されるようにする。

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

第43回 プライバシーレポートを表示する (タブブラウザーを作る)

tabbrowser177.gif
前回はステータスバーにいくつかのペインを作った。今回はそのペインのダブルクリックで開いているページのプライバシーレポートを表示する。

「プライバシーレポート」はInternet Explrer 6から追加された機能で、そのページに含まれるクッキーなどの情報が表示される。

まず内部で利用するための独自メッセージを定義する。次回のことも考え今回はプライバシーレポートに加え、セキュリティレポート用のメッセージも追加した。
#define	WM_DNP_CHANGEFOCUS		(WM_APP + 1)
#define	WM_DNP_CREATENEWTAB		(WM_APP + 2)
#define	WM_DNP_CHANGEADDRESS	(WM_APP + 3)
#define	WM_DNP_SCRIPTERROR		(WM_APP + 6)
#define	WM_DNP_SHOWSCRIPTERROR	(WM_APP + 7)
#define	WM_DNP_SHOWPRIVACYREPORT	(WM_APP + 8)		//■追加
#define	WM_DNP_SHOWPSECURITYREPORT	(WM_APP + 9)		//■追加

tabbrowser178.gif CIELikeStatusbarのダブルクリック処理部分を変更する。switchによる分岐にし、先ほど用意した独自メッセージをビューウインドウに飛ばすように設定する。
	//ステータスバーのダブルクリック処理
	LRESULT OnLButtonDblClk(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		int		i;
		RECT	rect;
		BOOL	ret;
		POINT	pt;

		CStatusBarCtrl	wndStatusBar = m_hWnd;

		if(_hWndNotify == NULL || ::IsWindow(_hWndNotify) == FALSE)
			return	0;		//通知先が死んでいたらこれ以降処理しない

		::GetCursorPos(&pt);
		ScreenToClient(&pt);

		i = 0;
		while(1)
		{
			ret = wndStatusBar.GetRect(i,&rect);
			if(ret == FALSE)
				break;

			if(::PtInRect(&rect,pt))
			{
				//i番目のペインがダブルクリックされた

				//■処理内容変更。switch化した
				switch(i)
				{
				case	PAIN_DEFAULT:
					::SendMessage(_hWndNotify,WM_DNP_SHOWSCRIPTERROR,NULL,NULL);
					break;

				case	PAIN_PRIVACY_REPORT:
					::SendMessage(_hWndNotify,WM_DNP_SHOWPRIVACYREPORT,NULL,NULL);
					break;

				case	PAIN_SECURITY_REPORT:
					::SendMessage(_hWndNotify,WM_DNP_SHOWPSECURITYREPORT,NULL,NULL);
					break;

				case	PAIN_PROGRESS:
				case	PAIN_RESERVED:
				case	PAIN_POPUP:
				case	PAIN_ADDON:
				case	PAIN_SECURITY:
				case	PAIN_ZONE:
				case	PAIN_BLOCKED:
				case	PAIN_ZOOM:
					break;
				}

				break;
			}

			i++;
		}

		return	0;
	}

tabbrowser179.gif そしてビューウインドウ内でメッセージを受け取り、レポートを表示する関数が実行されるようにする。
	BEGIN_MSG_MAP(CTabBrowser100View)
		MESSAGE_HANDLER(WM_DNP_SCRIPTERROR, OnDnpScriptError)
		MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
		MESSAGE_HANDLER(WM_DNP_SHOWSCRIPTERROR, OnShowScriptError)
		MESSAGE_HANDLER(WM_DNP_SHOWPRIVACYREPORT, OnShowPrivacyReport)		//■追加
		MESSAGE_HANDLER(WM_DNP_SHOWPSECURITYREPORT, OnShowSecurityReport)	//■追加
	END_MSG_MAP()


private:


	//■追加
	LRESULT OnShowPrivacyReport(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		ShowPrivacyReport(m_hWnd);
		return	0;
	}

	//■追加
	LRESULT OnShowSecurityReport(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		ShowSecurityReport(m_hWnd);
		return	0;
	}

tabbrowser180.gif
CIEUtilityの中にレポートを表示する関数を追加する。

プライバシーレポートの表示にはshdocvw.dllからエクスポートされるDoPrivavcyDlgという関数を使う。引数にIEnumPrivacyRecordsとURLが必要なのでそれをIWebBrowser2から取得し渡している。
	//■追加
	//IE6以上で実装されているプライバシーレポートの表示
	bool	ShowPrivacyReport(HWND hWnd)
	{
		HRESULT		hr;
		CComBSTR	bstr;
		HINSTANCE	hDLL;
		CComPtr<IServiceProvider>		pIServiceProvider;
		CComPtr<IEnumPrivacyRecords>	pIEnumPrivacyRecords;
		HRESULT (WINAPI* pfnDoPrivacyDlg)(HWND,LPOLESTR,IEnumPrivacyRecords*,BOOL) = NULL;

		if(_pIWebBrowser2 == NULL)
			return	false;

		//IEnumPrivacyRecords取得
		_pIWebBrowser2->QueryInterface(&pIServiceProvider);
		if(pIServiceProvider)
			pIServiceProvider->QueryService(__uuidof(IEnumPrivacyRecords),IID_IEnumPrivacyRecords,(void**)&pIEnumPrivacyRecords);
		if(pIEnumPrivacyRecords == NULL)
			return	false;

		//URL取得
		hr = _pIWebBrowser2->get_LocationURL(&bstr);
		if(FAILED(hr))
			return	false;

		hDLL = ::LoadLibrary(_T("shdocvw.dll"));
		if(hDLL == NULL)
			return	false;

		//DoPrivacyDlg取得
		(FARPROC&)pfnDoPrivacyDlg = ::GetProcAddress(hDLL,"DoPrivacyDlg");
		if(pfnDoPrivacyDlg == NULL)
		{
			::FreeLibrary(hDLL);
			return	false;
		}

		hr = pfnDoPrivacyDlg(hWnd,bstr,pIEnumPrivacyRecords,FALSE);

		::FreeLibrary(hDLL);

		return	SUCCEEDED(hr) ? true : false;
	}

	//■追加
	bool	ShowSecurityReport(HWND hWnd)
	{
		return	true;
	}

tabbrowser181.gif
これでステータスバーのプライバシーレポート用のペインをダブルクリックすることでプライバシーレポートが表示されるようになった。

次回はセキュリティレポートが表示されるようにする。

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

第42回 ステータスバーにペインを用意する (タブブラウザーを作る)

tabbrowser171.gif
前回まで少し機能拡張を休んでソースコードの整理を行っていた。今回はCIELikeStatusbarクラスを修正してステータスバーのペインを増やす。

ステータスバーでは複数のペインを扱うと、どのペインがどのインデックスなのかごちゃごちゃして分かりにくくなることがある。それを防ぐため今回はenumでペインを定義してしまう。
	//■処理変更
	LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		bHandled = FALSE;

		UpdateLayout();

		return	0;
	}


	//■追加
	//ステータスバーペインのインデックス
	enum	ENUM_PAIN
	{
		PAIN_DEFAULT = 0,			//メッセージ表示やアイコン表示
		PAIN_PROGRESS,				//プログレスバー表示
		PAIN_RESERVED,				//
		PAIN_POPUP,					//ポップアップブロック有効/無効
		PAIN_ADDON,					//アドオンの管理
		PAIN_PRIVACY_REPORT,		//クッキーアイコンやプライバシーレポート表示
		PAIN_SECURITY_REPORT,		//SSLアイコンやセキュリティレポート表示
		PAIN_SECURITY,				//SmartFilterなどの設定
		PAIN_ZONE,					//現在のゾーン表示
		PAIN_BLOCKED,				//ブロックされた項目の表示
		PAIN_ZOOM,					//ズーム設定


		PAIN_LAST					//インデックス数を示す。必ずenumの最後に配置すること
	};

tabbrowser172.gif 指定されたペインの横幅を返す関数を用意する。ペインのスペルがPAINになったりPANEになったり統一感がないが、細かいことは気にせずそのうち修正することにして今回は保留しておく。
	//■追加
	//ペインの「幅」を返す
	int	GetPaneWidth(UINT nIndex)
	{
		if(nIndex >= PAIN_LAST)
			return	0;

		switch(nIndex)
		{
		case	PAIN_DEFAULT:
			{
				int		i;
				int		nWidth;
				CRect	rect;

				//PAIN_DEFAULT以外の部分の幅を計算
				nWidth = 0;
				for(i = 1; i < PAIN_LAST; i++)
					nWidth += GetPaneWidth(i);

				//ステータスバー幅から合計幅を引いた値がPAIN_DEFAULTの幅
				GetClientRect(&rect);
				nWidth = rect.Width() - nWidth;

				if(nWidth >= 0)
					return	nWidth;

				return	0;			//マイナスになるならゼロを返す
			}
			break;

		case	PAIN_PROGRESS:
			if(_nLastProgressMax < _nLastProgress)
				return	0;
			return	100;

		case	PAIN_RESERVED:
		case	PAIN_POPUP:
		case	PAIN_ADDON:
		case	PAIN_PRIVACY_REPORT:
		case	PAIN_SECURITY_REPORT:
		case	PAIN_SECURITY:
			return	20;

		case	PAIN_ZONE:
			return	100;

		case	PAIN_BLOCKED:
			return	30;

		case	PAIN_ZOOM:
			return	60;
		}

		ATLASSERT(0);
		return	0;
	}

tabbrowser173.gif ステータスバーのレイアウトを設定する関数。ステータスバーのレイアウトはSetParts(SB_SETPARTS)で設定できるが、この関数の引数に渡す整数配列は、ペインの「幅」ではなく、右側の「座標」になることに注意。GetPaneWidthの引数をそのまま渡すことはできない。
	//■追加
	//ステータスバーレイアウト設定
	bool	UpdateLayout(void)
	{
		if(IsWindow() == FALSE)
			return	false;				//ステータスバー表示してない

		//ステータスバーのペイン作成
		//本当は現在のペイン数などを見て更新した方がいいのだろうけど、面倒だからそのまま設定
		{
			int		i;
			int		pnParts[PAIN_LAST];
			int		nOffset;
			CStatusBarCtrl	wndStatusBar = m_hWnd;

			nOffset = 0;
			for(i = 0; i < PAIN_LAST; i++)
			{
				pnParts[i] = GetPaneWidth(i) + nOffset;
				nOffset = pnParts[i];						//pnPartsは「幅」ではなく座標を入れる必要があるので、幅から座標に変換するためnOffsetを利用
			}

			//ペイン作成
			wndStatusBar.SetParts(PAIN_LAST,pnParts);
		}

		RefreshProgressBar();		//プログレスバー表示更新

		return	true;
	}

tabbrowser174.gif これまではプログレスバーの進行状況設定時にステータスバーのペインを設定していた。これからはUpdateLayoutがその役を担うことになるので、ペイン作成関連処理を削除し、またきちんとUpdateLayoutが呼ばれるようにしておく。
	//bVisible=falseならプログレスバーを消す
	//nProgress < 0、nProgressMax < 0ならプログレス設定はしない
	//nProgressMax < nProgressなら強制的に非表示にする
	bool	RefreshProgressBar(int nProgress=-1,int nProgressMax=-1,bool bVisible=true)
	{
		if((nProgress >= 0 && nProgressMax  >= 0) || (nProgressMax < nProgress))
		{
			//状態を保存しておく
			_nLastProgress		= nProgress;
			_nLastProgressMax	= nProgressMax;
		}

		if(::IsWindow(m_hWnd) == FALSE)
			return	false;				//ステータスバー表示してない

		//■削除
		//int		nProgressWidth = 100;			//■プログレスバーの幅は100px固定とする
		CRect	rect;
		CStatusBarCtrl	wndStatusBar = m_hWnd;

		if(_nLastProgressMax < _nLastProgress)
			bVisible = false;


		//■追加
		if(bVisible == false)
		{
			int		nRet;
			int		pnParts[PAIN_LAST];

			nRet = wndStatusBar.GetParts(PAIN_LAST,pnParts);

			if(nRet > PAIN_PROGRESS)
			{
				if(pnParts[PAIN_PROGRESS] != pnParts[PAIN_PROGRESS - 1])
					UpdateLayout();
			}
		}


		//■削除
		//if(bVisible == false)
		//	nProgressWidth = 0;

		//■削除
		////ステータスバーのペインの作成/更新
		//{
		//	int		pnParts[2];						//2つペインを作成(1つはデフォルト、もう1つはプログレスバー用)

		//	wndStatusBar.GetClientRect(&rect);
		//	pnParts[0] = rect.Width() - nProgressWidth;
		//	pnParts[1] = rect.Width();

		//	wndStatusBar.SetParts(sizeof(pnParts) / sizeof(pnParts[0]),pnParts);
		//}


		//プログレスバーの生成/更新
		{
			wndStatusBar.GetRect(1,&rect);			//2つめのペインをプログレスバーに利用する

			if(_wndProgressBar.IsWindow() == FALSE)
				_wndProgressBar.Create(m_hWnd,rect,0,WS_CHILD);	//プログレスバーを生成
			else
				_wndProgressBar.MoveWindow(&rect);			//位置を移動

			if(bVisible)
			{
				if(_wndProgressBar.IsWindowVisible() == FALSE)
					_wndProgressBar.ShowWindow(SW_NORMAL);		//可視に
			}
			else
			{
				if(_wndProgressBar.IsWindowVisible())
					_wndProgressBar.ShowWindow(SW_HIDE);		//不可視に
			}

			//プログレスの設定
			if(_nLastProgress >= 0)
				_wndProgressBar.SetRange(0,_nLastProgressMax);
			if(_nLastProgress >= 0)
				_wndProgressBar.SetPos(_nLastProgress);
		}

		return	true;
	}

tabbrowser175.gif 外部から呼ばれるステータスバー更新用関数内でもUpdateLayoutが呼ばれるようにしておく。UpdateLayout内ではプログレスバーの設定もしているのでRefresh内のプログレスバー更新処理は削除した。
	//ステータスバー表示更新
	bool	Refresh(bool bCapture)
	{
		if(bCapture == false)
		{
			if(_wndProgressBar.IsWindow())
			{
				if(_wndProgressBar.IsWindowVisible())
					_wndProgressBar.ShowWindow(SW_HIDE);		//不可視に
			}
			return	true;
		}

		if(IsWindow() == FALSE)
			return	false;

		//■追加
		UpdateLayout();		//レイアウト調整

		//ステータスバーのテキスト変更
		{
			SetText(_strText);
		}

		//ステータスバーのエラーアイコン変更
		{
			CStatusBarCtrl	wndStatusBar = m_hWnd;

			if(_bPageError)
				wndStatusBar.SetIcon(0,_cIconList.GetIcon(CIconManager::ICON_WARNING_SM));
			else
				wndStatusBar.SetIcon(0,NULL);
		}

		//■削除
		////プログレス変更
		//{
		//	RefreshProgressBar(_nLastProgress,_nLastProgressMax);
		//}

		return	true;
	}

tabbrowser176.gif
これでビルド/実行するとステータスバーにペインが増えた。

次回はステータスバーがダブルクリックされたときにプライバシーレポートの表示をする。

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

2009年04月08日

第41回 ソースコードを少し整理する (タブブラウザーを作る)

前に一度ソースコードを整理したが、またゴチャゴチャしてきたので再び軽く整理する。




コメントアウト処理を削除

ステータスバー関連処理の再実装をするときにCMainFrame内の処理をたくさんコメントアウトした。それがそのまま残っているのでそれらを削除した。

コメントアウトされている部分で、メニュー項目を無効にする処理でコメントに「//有効/無効設定必要」と置いている部分は削除せずに残しておいた。




クラスを独立したヘッダーファイルへ

今までTabBrowser100View.hの中に多くのクラスを実装した。それらを全部独立した「.h」ファイルに分けた。基本的にカット&ペーストでいいが、#includeの定義を忘れないように。




内部処理をprivate宣言に

CIELikeStatusbarとCTabBrowser100View内の関数や変数はそのほとんどをpublic宣言にしていた。そのためどれが内部使用のみでどれが外部から呼ばれるのかがまったくわからなくなっていた。

そのため内部利用のみのものはprivate、外部から呼ばれるものはpublic宣言に変更しておいた。












次回は今後の機能拡張のためにステータスバーにペインを増やす。


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

第40回 ステータスバーダブルクリック処理を再実装する (タブブラウザーを作る)

tabbrowser166.gif
前回はステータスバーへメッセージやアイコンを表示する部分を再実装した。今回はスクリプトエラーが発生しているときにステータスバーのダブルクリックでエラーの詳細情報を表示する処理を再実装する。

ステータスバー用のクラスCIELikeStatusbarへダブルクリックを検出するためのメッセージ処理を追加する。これまではメインウインドウでNM_DBLCLKを処理することで簡単にダブルクリックされたペインまで取得できた。しかし今回はペインのRECTからダブルクリックされたペインを計算している。
class	CIELikeStatusbar	: public CWindowImpl<CIELikeStatusbar>
{
	CIconManager	_cIconList;

	CProgressBarCtrl	_wndProgressBar;			//ステータスバーに配置するプログレスバーコントロール


	CAtlString	_strText;

	long	_nLastProgress;			//最後に受け取ったプログレス情報
	long	_nLastProgressMax;		//最後に受け取ったプログレス最大値

	bool	_bPageError;	//現在のページでスクリプトエラーなどがあればtrue、通常はfalse

	HWND	_hWndNotify;	//■追加 ダブルクリック通知先。通常ビューウインドウのHWND
public:

	CIELikeStatusbar()
	{
		_hWndNotify			= NULL;		//■追加
		_nLastProgress		= -1;
		_nLastProgressMax	= -1;
		_bPageError = false;
	}


	BEGIN_MSG_MAP(CIELikeStatusbar)
		MESSAGE_HANDLER(WM_SIZE, OnSize)
		MESSAGE_HANDLER(WM_LBUTTONDBLCLK, OnLButtonDblClk)		//■追加
	END_MSG_MAP()


	//■追加
	//ステータスバーのダブルクリック処理
	LRESULT OnLButtonDblClk(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		int		i;
		RECT	rect;
		BOOL	ret;
		POINT	pt;

		CStatusBarCtrl	wndStatusBar = m_hWnd;

		if(_hWndNotify == NULL || ::IsWindow(_hWndNotify) == FALSE)
			return	0;		//通知先が死んでいたらこれ以降処理しない

		::GetCursorPos(&pt);
		ScreenToClient(&pt);

		i = 0;
		while(1)
		{
			ret = wndStatusBar.GetRect(i,&rect);
			if(ret == FALSE)
				break;

			if(::PtInRect(&rect,pt))
			{
				//i番目のペインがダブルクリックされた
				if(i == 0)
					::SendMessage(_hWndNotify,WM_DNP_SHOWSCRIPTERROR,NULL,NULL);

				break;
			}

			i++;
		}

		return	0;
	}

	//■追加
	BOOL	SubclassWindow(HWND hWnd,HWND hWndNotify)
	{
		_hWndNotify = hWndNotify;

		return	__super::SubclassWindow(hWnd);
	}

tabbrowser167.gif そしてステータスバークラスから送られてきた独自メッセージのハンドラをビュークラスに追加する。
	BEGIN_MSG_MAP(CTabBrowser100View)
		MESSAGE_HANDLER(WM_DNP_SCRIPTERROR, OnDnpScriptError)
		MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
		MESSAGE_HANDLER(WM_DNP_SHOWSCRIPTERROR, OnShowScriptError)		//■追加
	END_MSG_MAP()

tabbrowser168.gif また、サブクラス化するときにビュークラスのHWNDがステータスバーにわたるようにしておく。
	//■追加
	LRESULT OnShowScriptError(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		ShowScriptError();
		return	0;
	}

	CIELikeStatusbar	_wndStatusbar;


	//メインウインドウから呼ばれる
	//bCapture=trueでこのビューがステータスバーを制御する
	//bCapture=falseでこのビューがステータスバーを解放する
	bool	SetStatusBar(HWND hWnd,bool bCapture)
	{
		if(bCapture)
		{
			if(_wndStatusbar.IsWindow())
				return	false;
			_wndStatusbar.SubclassWindow(hWnd,m_hWnd);			//■変更
			_wndStatusbar.Refresh(true);
		}
		else
		{
			if(_wndStatusbar.IsWindow())
				_wndStatusbar.UnsubclassWindow();
			_wndStatusbar.Refresh(false);
		}

		return	true;
	}

tabbrowser169.gif 最後に「stdafx.h」で新しい独自メッセージWM_DNP_SHOWSCRIPTERRORを追加する。また不要になって使われていないメッセージを削除しておいた。
#define	WM_DNP_CHANGEFOCUS		(WM_APP + 1)
#define	WM_DNP_CREATENEWTAB		(WM_APP + 2)
#define	WM_DNP_CHANGEADDRESS	(WM_APP + 3)
//#define	WM_DNP_CHANGESTATUSTEXT	(WM_APP + 4)		//■削除
//#define	WM_DNP_CHANGEPROGRESS	(WM_APP + 5)		//■削除
#define	WM_DNP_SCRIPTERROR		(WM_APP + 6)
#define	WM_DNP_SHOWSCRIPTERROR	(WM_APP + 7)		//■追加

tabbrowser170.gif
これでビルド/実行すると再びスクリプトエラーの詳細情報を見れるようになった。

だんだんソースコードが増えてきたので、次回は少しソースコードを整理する。

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

第39回 ステータスバー関連処理の再実装する (タブブラウザーを作る)

tabbrowser160.gif
前回はステータスバー関連処理を見直す前段階として「MainFrm.h」内の処理をコメントアウトした。今回はコメントアウトした処理を参考にしながらステータスバー関連処理を新しく作り直す。

まず「MainFrm.h」からCIconManagerを移動してくる。そしてスタータスバー用のクラスCIELikeStatusbarを作る。処理内容はCMainFrameから移動してきたものに少し変更を加えた程度だ。
#include "atlcoll.h"

//■CMainFrameから移動
//アイコンを管理
//アイコンをAddする関数などは未実装。今後追加
class	CIconManager
{
protected:
	CAtlArray<HICON>	_ahIcon;		//アイコンリスト

public:
	CIconManager()
	{
		SetFixedIndexIcon();		//固定インデックスのアイコンを追加
	}

	~CIconManager()
	{
		Destroy();
	}

	enum	ICON_INDEX
	{
		ICON_WARNING_SM = 0,			//警告アイコン。スクリプトエラー時に利用
	};

	HICON	GetIcon(UINT nIconIndex)
	{
		if(nIconIndex >= _ahIcon.GetCount())
			return	NULL;

		return	_ahIcon[nIconIndex];
	}

protected:

	//固定インデックスのアイコンを追加
	//かならずICON_INDEXと同じ値になるようにする
	bool	SetFixedIndexIcon(void)
	{
		ATLASSERT(_ahIcon.GetCount() == 0);		//すでに設定されてる?
		if(_ahIcon.GetCount())
			return	false;

		size_t	nIndex;
		HICON	hIcon;

		//警告アイコン
		//LoadImageで32x32を読み込み、CopyImageで16x16に縮小。LoadImageのHICONはLR_SHAREDなのでDestroyIcon必要なし
		hIcon = (HICON)::LoadImage(NULL,MAKEINTRESOURCE(OIC_WARNING),IMAGE_ICON,0,0,LR_DEFAULTSIZE | LR_SHARED);
		hIcon = (HICON)::CopyImage(hIcon,IMAGE_ICON,::GetSystemMetrics(SM_CXSMICON),::GetSystemMetrics(SM_CYSMICON),LR_COPYFROMRESOURCE);
		nIndex = _ahIcon.Add(hIcon);
		ATLASSERT(nIndex == ICON_WARNING_SM);

		return	true;
	}

	//保持してるアイコンの破棄
	void	Destroy(void)
	{
		size_t	i;
		size_t	nSize;

		nSize = _ahIcon.GetCount();
		for(i = 0; i < nSize; i++)
		{
			if(_ahIcon[i] == NULL)
				continue;
			::DestroyIcon(_ahIcon[i]);
		}
		_ahIcon.RemoveAll();
	}
};




//■追加
class	CIELikeStatusbar	: public CWindowImpl<CIELikeStatusbar>
{

	//■CMainFrameから移動
	CIconManager	_cIconList;

	//■CMainFrameから移動
	CProgressBarCtrl	_wndProgressBar;			//ステータスバーに配置するプログレスバーコントロール


	CAtlString	_strText;

	//■CTabBrowser100Viewから移動
	long	_nLastProgress;			//最後に受け取ったプログレス情報
	long	_nLastProgressMax;		//最後に受け取ったプログレス最大値

	//■CTabBrowser100Viewから移動
	bool	_bPageError;	//現在のページでスクリプトエラーなどがあればtrue、通常はfalse

public:

	CIELikeStatusbar()
	{
		_nLastProgress		= -1;
		_nLastProgressMax	= -1;
		_bPageError = false;
	}


	BEGIN_MSG_MAP(CIELikeStatusbar)
		MESSAGE_HANDLER(WM_SIZE, OnSize)		//■CMainFrameから移動
	END_MSG_MAP()


	//■CMainFrameから移動
	LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		bHandled = FALSE;

		if(_wndProgressBar.IsWindow())
			RefreshProgressBar();		//プログレスバー表示更新

		return	0;
	}


	//■CMainFrameから移動。m_hWndStatusBarをm_hWndに変更
	//bVisible=falseならプログレスバーを消す
	//nProgress < 0、nProgressMax < 0ならプログレス設定はしない
	//nProgressMax < nProgressなら強制的に非表示にする
	bool	RefreshProgressBar(int nProgress=-1,int nProgressMax=-1,bool bVisible=true)
	{
		//■追加
		if((nProgress >= 0 && nProgressMax  >= 0) || (nProgressMax < nProgress))
		{
			//状態を保存しておく
			_nLastProgress		= nProgress;
			_nLastProgressMax	= nProgressMax;
		}

		if(::IsWindow(m_hWnd) == FALSE)
			return	false;				//ステータスバー表示してない

		int		nProgressWidth = 100;			//■プログレスバーの幅は100px固定とする
		CRect	rect;
		CStatusBarCtrl	wndStatusBar = m_hWnd;

		if(_nLastProgressMax < _nLastProgress)		//■変更
			bVisible = false;

		if(bVisible == false)
			nProgressWidth = 0;

		//ステータスバーのペインの作成/更新
		{
			int		pnParts[2];						//2つペインを作成(1つはデフォルト、もう1つはプログレスバー用)

			wndStatusBar.GetClientRect(&rect);
			pnParts[0] = rect.Width() - nProgressWidth;
			pnParts[1] = rect.Width();

			wndStatusBar.SetParts(sizeof(pnParts) / sizeof(pnParts[0]),pnParts);
		}


		//プログレスバーの生成/更新
		{
			wndStatusBar.GetRect(1,&rect);			//2つめのペインをプログレスバーに利用する

			if(_wndProgressBar.IsWindow() == FALSE)
				_wndProgressBar.Create(m_hWnd,rect,0,WS_CHILD);	//プログレスバーを生成
			else
				_wndProgressBar.MoveWindow(&rect);			//位置を移動

			if(bVisible)
			{
				if(_wndProgressBar.IsWindowVisible() == FALSE)
					_wndProgressBar.ShowWindow(SW_NORMAL);		//可視に
			}
			else
			{
				if(_wndProgressBar.IsWindowVisible())
					_wndProgressBar.ShowWindow(SW_HIDE);		//不可視に
			}

			//■変更
			//プログレスの設定
			if(_nLastProgress >= 0)
				_wndProgressBar.SetRange(0,_nLastProgressMax);
			if(_nLastProgress >= 0)
				_wndProgressBar.SetPos(_nLastProgress);
		}

		return	true;
	}




	//ステータスバー表示更新
	bool	Refresh(bool bCapture)
	{
		if(bCapture == false)
		{
			if(_wndProgressBar.IsWindow())
			{
				if(_wndProgressBar.IsWindowVisible())
					_wndProgressBar.ShowWindow(SW_HIDE);		//不可視に
			}
			return	true;
		}

		if(IsWindow() == FALSE)
			return	false;

		//ステータスバーのテキスト変更
		{
			SetText(_strText);
		}

		//ステータスバーのエラーアイコン変更
		{
			CStatusBarCtrl	wndStatusBar = m_hWnd;

			if(_bPageError)
				wndStatusBar.SetIcon(0,_cIconList.GetIcon(CIconManager::ICON_WARNING_SM));
			else
				wndStatusBar.SetIcon(0,NULL);
		}

		//プログレス変更
		{
			RefreshProgressBar(_nLastProgress,_nLastProgressMax);
		}

		return	true;
	}


	bool	SetText(LPCTSTR pszText)
	{
		_strText = pszText;

		if(IsWindow() == FALSE)
			return	true;

		SetWindowText(pszText);

		return	true;
	}

	bool	SetPageError(bool bError)
	{
		_bPageError = bError;			//エラーが発生したことを保持

		if(IsWindow())
		{
			CStatusBarCtrl	wndStatusBar = m_hWnd;

			if(_bPageError)
				wndStatusBar.SetIcon(0,_cIconList.GetIcon(CIconManager::ICON_WARNING_SM));
			else
				wndStatusBar.SetIcon(0,NULL);
		}

		return	true;
	}
};

tabbrowser162.gif そしてビュークラス内のステータスバー関連処理をCIELikeStatusbarを利用するものに変更しいらない部分を削除する。
	//■処理内容変更
	//ステータスバーのメッセージ変更
	void	ChangeStatusText(LPCTSTR pszText)
	{
		_strLastStatusText = pszText;		//いつでも参照できるようにクラスのメンバーに保存しておく

		GetLastStatusText(_strLastStatusText);

		_wndStatusbar.SetText(_strLastStatusText);
	}

	void __stdcall OnStatusTextChange(BSTR bstrText)
	{
		ChangeStatusText((CAtlString)bstrText);
	}


	//■処理内容変更
	//エラー発生/解消時に呼ぶ
	//bError=trueならエラー発生
	void	SetErrorState(bool bError)
	{
		_bPageError = bError;

		if(bError)
			ChangeStatusText(NULL);

		_wndStatusbar.SetPageError(bError);
	}

	//■削除
	//bool	IsPageError(void)
	//{
	//	return	_bPageError;
	//}

	LRESULT OnDnpScriptError(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		SetErrorState(true);
		return	0;
	}

	//最後にIEコントロールから受け取ったステータスバー用メッセージを返す
	void	GetLastStatusText(CAtlString& strText)
	{
		strText = _strLastStatusText;

		//表示する文字がないときで、現在ページにエラーがあればエラーメッセージを返す
		if(_bPageError && strText == _T(""))
			strText = _T("ページでエラーが発生しました。");
	}

	void __stdcall OnDownloadComplete()
	{
	}

	void __stdcall OnCommandStateChange(long lCommand,VARIANT_BOOL vbEnable)
	{
	}

	void __stdcall OnDownloadBegin(void)
	{
		SetErrorState(false);		//エラー情報をリセット
	}


	//■削除
	//long	_nLastProgress;			//最後に受け取ったプログレス情報
	//long	_nLastProgressMax;		//最後に受け取ったプログレス最大値



	//■処理内容変更
	void __stdcall OnProgressChange(long lProgress,long lProgressMax)
	{
		if(lProgress < 0 || (lProgressMax == 0 && lProgress == 0))	//MSDNには記述がないが(0,0)で終わることが多いため(0,0)でも非表示
			lProgressMax = lProgress - 1;		//lProgressMax < lProgress にしておく -> 自動的にプログレスバーが消える

		_wndStatusbar.RefreshProgressBar(lProgress,lProgressMax);
	}


	//■削除
	////最後にIEコントロールから受け取ったプログレス情報を返す
	//void	GetLastProgress(long& nProgress,long& nProgressMax)
	//{
	//	nProgress		= _nLastProgress;
	//	nProgressMax	= _nLastProgressMax;
	//}

tabbrowser161.gif コンストラクタの不要部分も忘れずにコメントアウトしておく。
	CTabBrowser100View(CTabView* pTabView,HWND hWndRebarIE)
	{
		_pTabView = pTabView;
//		_nLastProgress		= 0;		//■削除
//		_nLastProgressMax	= -1;		//■削除
		_hWndRebarIE = hWndRebarIE;
		_bPageError = false;
	}

tabbrowser163.gif 今回の修正ではビュークラス側から直接ステータスバーに文字表示などを行っている。そのままだと複数のタブ(ビュー)が開いているときに、複数のビューからステータスバーにアクセスしてしまうことになるので、タブ(ビュー)がアクティブなときだけステータスバーへのアクセスが有効になるようにする。
	CIELikeStatusbar	_wndStatusbar;		//■追加


	//■追加
	//メインウインドウから呼ばれる
	//bCapture=trueでこのビューがステータスバーを制御する
	//bCapture=falseでこのビューがステータスバーを解放する
	bool	SetStatusBar(HWND hWnd,bool bCapture)
	{
		if(bCapture)
		{
			if(_wndStatusbar.IsWindow())
				return	false;
			_wndStatusbar.SubclassWindow(hWnd);
			_wndStatusbar.Refresh(true);
		}
		else
		{
			if(_wndStatusbar.IsWindow())
				_wndStatusbar.UnsubclassWindow();
			_wndStatusbar.Refresh(false);
		}

		return	true;
	}

tabbrowser164.gif 「MainFrm.h」内でアクティブなビューにだけステータスバーを渡す。
	//タブが選択されたときの処理
	LRESULT OnTabPageActivated(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
	{
		if(pnmh == NULL)
			return	0;

		//全てのビューに対してタブ変更があったことを通知
		{
			int		i;
			int		nCount;
			CTabBrowser100View*	pView;

			nCount = m_view.GetPageCount();
			for(i = 0; i < nCount; i++)
			{
				pView = GetPageView(i);
				if(pView == NULL)
					continue;

				//■処理変更
				if(pnmh->idFrom == i)
					pView->OnTabPageChange(true);
				else
				{
					pView->OnTabPageChange(false);
					pView->SetStatusBar(m_hWndStatusBar,false);	//ステータスバー解放
				}
			}

			//■3行追加
			pView = GetActivePageView();
			if(pView)
				pView->SetStatusBar(m_hWndStatusBar,true);		//ステータスバーセット
		}


		bool		ret;
		CTabBrowser100View*	pView;

		pView = GetActivePageView();		//アクティブビュー取得
		if(pView == NULL)
			return	0;

		//アドレスバーのURL変更
		{
			CAtlString	strURL;

			ret = pView->GetURL(strURL);		//URL取得
			if(ret)
				_wndAddressBar.SetWindowText(strURL);
		}

		return	0;
	}

tabbrowser165.gif
これでビルド/実行すると再びステータスバーへの表示が行われるようになった。

しかしまだステータスバーのダブルクリックに関する処理を再実装していない。次回はそれを行う。

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

第38回 ステータスバー関連処理の実装を見直す (タブブラウザーを作る)

tabbrowser156.gif
これまでにステータスバーにIEコントロールからのメッセージを表示、スクリプトエラーがあったときにエラーメッセージとアイコンの表示、スクリプトエラー時にダブルクリックでエラーの詳細情報を表示する機能を実装した。

しかしその過程でかなりソースコードがゴチャゴチャして崩壊寸前にまで追い込まれている。これからステータスバー関連の処理を整理する。まずはその前段階としてMainFrm.h内のステータスバー関連処理をすべてコメントアウトしてしまう。

ステータスバーの処理はビューからメインウインドウへメッセージを送ることで開始していた。それらのメッセージマップをコメントアウトする。
	BEGIN_MSG_MAP(CMainFrame)
		MESSAGE_HANDLER(WM_DNP_CREATENEWTAB, OnDnpCreateNewTab)
		MESSAGE_HANDLER(WM_DNP_CHANGEFOCUS, OnDnpChangeFocus)
		MESSAGE_HANDLER(WM_DNP_CHANGEADDRESS, OnDnpChangeAddress)
//		MESSAGE_HANDLER(WM_DNP_CHANGESTATUSTEXT, OnDnpChangeStatusText)	//■コメントアウト
//		MESSAGE_HANDLER(WM_DNP_CHANGEPROGRESS, OnDnpChangeProgress)		//■コメントアウト
//		MESSAGE_HANDLER(WM_DNP_SCRIPTERROR, OnDnpScriptError)			//■コメントアウト
		NOTIFY_CODE_HANDLER(CBEN_ENDEDIT, OnAddressbarEnter)
		MESSAGE_HANDLER(WM_CREATE, OnCreate)
		MESSAGE_HANDLER(WM_DESTROY, OnDestroy)
		COMMAND_ID_HANDLER(ID_APP_EXIT, OnFileExit)
		COMMAND_ID_HANDLER(ID_FILE_NEW, OnFileNew)
		COMMAND_ID_HANDLER(ID_VIEW_TOOLBAR, OnViewToolBar)
		COMMAND_ID_HANDLER(ID_VIEW_STATUS_BAR, OnViewStatusBar)
		COMMAND_ID_HANDLER(ID_APP_ABOUT, OnAppAbout)
		COMMAND_ID_HANDLER(ID_WINDOW_CLOSE, OnWindowClose)
		COMMAND_ID_HANDLER(ID_WINDOW_CLOSE_ALL, OnWindowCloseAll)
		COMMAND_ID_HANDLER(ID_FILE_PRINT, OnFileCommand)
		COMMAND_ID_HANDLER(ID_FILE_PRINT_PREVIEW, OnFileCommand)
		COMMAND_ID_HANDLER(ID_FILE_PRINT_SETUP, OnFileCommand)
		COMMAND_ID_HANDLER(ID_EDIT_COPY, OnFileCommand)
		COMMAND_ID_HANDLER(ID_EDIT_CUT, OnFileCommand)
		COMMAND_ID_HANDLER(ID_EDIT_PASTE, OnFileCommand)
		COMMAND_ID_HANDLER(ID_EDIT_SELECT_ALL, OnFileCommand)
		COMMAND_ID_HANDLER(ID_FILE_SAVE, OnFileCommand)
		COMMAND_ID_HANDLER(ID_FILE_SAVE_AS, OnFileCommand)
		COMMAND_ID_HANDLER(ID_FILE_CREATE_SHORTCUT, OnFileCommand)
		COMMAND_ID_HANDLER(ID_FILE_PROPERTY, OnFileCommand)
		COMMAND_ID_HANDLER(ID_EDIT_FIND, OnFileCommand)
		COMMAND_RANGE_HANDLER(ID_WINDOW_TABFIRST, ID_WINDOW_TABLAST, OnWindowActivate)
		COMMAND_ID_HANDLER(ID_IE_BACK, OnIECommand)
		COMMAND_ID_HANDLER(ID_IE_NEXT, OnIECommand)
		COMMAND_ID_HANDLER(ID_IE_STOP, OnIECommand)
		COMMAND_ID_HANDLER(ID_IE_REFRESH, OnIECommand)
		COMMAND_ID_HANDLER(ID_IE_ADDFAVORITE, OnIEAddFavorite)
		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()

tabbrowser157.gif そして関連した関数とメンバー変数をコメントアウトする。
class CMainFrame : public CFrameWindowImpl<CMainFrame>, public CUpdateUI<CMainFrame>,
		public CMessageFilter, public CIdleHandler
{
	CAddressBarCtrl	_wndAddressBar;			// アドレスバー用コンボボックス

	////■コメントアウト
	//CIconManager	_cIconList;

public:

	////■コメントアウト
	////ステータスバーのダブルクリック処理
	//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;
	//}


	////■コメントアウト
	//LRESULT OnDnpChangeProgress(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	//{
	//	RefreshProgressBar((long)wParam,(long)lParam);
	//	return	0;
	//}


	////■コメントアウト
	//LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	//{
	//	bHandled = FALSE;

	//	if(_wndProgressBar.IsWindow())
	//		RefreshProgressBar();		//プログレスバー表示更新

	//	return	0;
	//}

	////■コメントアウト
	//CProgressBarCtrl	_wndProgressBar;			//ステータスバーに配置するプログレスバーコントロール

	////■コメントアウト
	////bVisible=falseならプログレスバーを消す
	////nProgress < 0、nProgressMax < 0ならプログレス設定はしない
	////nProgressMax < nProgressなら強制的に非表示にする
	//bool	RefreshProgressBar(int nProgress=-1,int nProgressMax=-1,bool bVisible=true)
	//{
	//	if(::IsWindow(m_hWndStatusBar) == FALSE)
	//		return	false;				//ステータスバーがない

	//	int		nProgressWidth = 100;			//■プログレスバーの幅は100px固定とする
	//	CRect	rect;
	//	CStatusBarCtrl	wndStatusBar = m_hWndStatusBar;

	//	if(nProgressMax < nProgress)
	//		bVisible = false;

	//	if(bVisible == false)
	//		nProgressWidth = 0;

	//	//ステータスバーのペインの作成/更新
	//	{
	//		int		pnParts[2];						//2つペインを作成(1つはデフォルト、もう1つはプログレスバー用)

	//		wndStatusBar.GetClientRect(&rect);
	//		pnParts[0] = rect.Width() - nProgressWidth;
	//		pnParts[1] = rect.Width();

	//		wndStatusBar.SetParts(sizeof(pnParts) / sizeof(pnParts[0]),pnParts);
	//	}


	//	//プログレスバーの生成/更新
	//	{
	//		wndStatusBar.GetRect(1,&rect);			//2つめのペインをプログレスバーに利用する

	//		if(_wndProgressBar.IsWindow() == FALSE)
	//			_wndProgressBar.Create(m_hWndStatusBar,rect,0,WS_CHILD);	//プログレスバーを生成
	//		else
	//			_wndProgressBar.MoveWindow(&rect);			//位置を移動

	//		if(bVisible)
	//		{
	//			if(_wndProgressBar.IsWindowVisible() == FALSE)
	//				_wndProgressBar.ShowWindow(SW_NORMAL);		//可視に
	//		}
	//		else
	//		{
	//			if(_wndProgressBar.IsWindowVisible())
	//				_wndProgressBar.ShowWindow(SW_HIDE);		//不可視に
	//		}

	//		//プログレスの設定
	//		if(nProgressMax >= 0)
	//			_wndProgressBar.SetRange(0,nProgressMax);
	//		if(nProgress >= 0)
	//			_wndProgressBar.SetPos(nProgress);
	//	}

	//	return	true;
	//}




	////■コメントアウト
	////ステータスバーの表示テキストの変更処理
	////アクティブなタブのIEでステータスバーのテキストが変わったときにメッセージが届く
	//LRESULT OnDnpChangeStatusText(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	//{
	//	LPCTSTR		pszText = (LPCTSTR)wParam;

	//	if(pszText == NULL)
	//		return	0;

	//	if(::IsWindow(m_hWndStatusBar))
	//		::SetWindowText(m_hWndStatusBar,pszText);

	//	return	0;
	//}

tabbrowser158.gif Visual Studioではコメントアウトしたい部分を選択して、[Ctrl+K]→[Ctrl+C]とキー操作をするとその部分がコメントアウトされる。逆にコメントを外したい場合は[Ctrl+U]とキー操作する。覚えておくと今回のようにコメントアウトする部分が多いときに便利だ。
	//タブが選択されたときの処理
	LRESULT OnTabPageActivated(int idCtrl, LPNMHDR pnmh, BOOL& bHandled)
	{
		if(pnmh == NULL)
			return	0;

		//全てのビューに対してタブ変更があったことを通知
		{
			int		i;
			int		nCount;
			CTabBrowser100View*	pView;

			int kk=m_view.GetActivePage();

			nCount = m_view.GetPageCount();
			for(i = 0; i < nCount; i++)
			{
				pView = GetPageView(i);
				if(pView == NULL)
					continue;

				if(pnmh->idFrom == i)
					pView->OnTabPageChange(true);
				else
					pView->OnTabPageChange(false);
			}
		}

		bool		ret;
		CTabBrowser100View*	pView;

		pView = GetActivePageView();		//アクティブビュー取得
		if(pView == NULL)
			return	0;

		//アドレスバーのURL変更
		{
			CAtlString	strURL;

			ret = pView->GetURL(strURL);		//URL取得
			if(ret)
				_wndAddressBar.SetWindowText(strURL);
		}

		////■コメントアウト
		////ステータスバーのテキスト変更
		//{
		//	CAtlString	strText;

		//	pView->GetLastStatusText(strText);
		//	if(::IsWindow(m_hWndStatusBar))
		//		::SetWindowText(m_hWndStatusBar,strText);
		//}

		////■コメントアウト
		////ステータスバーのエラーアイコン変更
		//{
		//	CStatusBarCtrl	wndStatusBar = m_hWndStatusBar;

		//	if(wndStatusBar.IsWindow())
		//	{
		//		if(pView->IsPageError())
		//			wndStatusBar.SetIcon(0,_cIconList.GetIcon(CIconManager::ICON_WARNING_SM));
		//		else
		//			wndStatusBar.SetIcon(0,NULL);
		//	}
		//}

		////■コメントアウト
		////プログレス変更
		//{
		//	long	nProgress;
		//	long	nProgressMax;

		//	pView->GetLastProgress(nProgress,nProgressMax);
		//	RefreshProgressBar(nProgress,nProgressMax);
		//}

		return	0;
	}


	////■コメントアウト
	////ステータスバーのエラーアイコン変更
	//LRESULT OnDnpScriptError(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	//{
	//	BOOL	bPageError = (BOOL)wParam;
	//	CStatusBarCtrl	wndStatusBar = m_hWndStatusBar;

	//	if(wndStatusBar.IsWindow())
	//	{
	//		if(bPageError)
	//			wndStatusBar.SetIcon(0,_cIconList.GetIcon(CIconManager::ICON_WARNING_SM));
	//		else
	//			wndStatusBar.SetIcon(0,NULL);
	//	}

	//	return	0;
	//}

tabbrowser159.gif
ビューウインドウ側からメッセージを送る部分はコメントアウトしていないが、これでビルド/実行するとステータスバー関連の機能がすべて使えなくなった。

次回はステータスバー関連機能の再実装を行う。

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

2009年04月07日

第37回 「プロパティ」「保存」「ページ内検索」「ショートカット作成」を実装する (タブブラウザーを作る)

tabbrowser152.gif
今回はいくつかの簡単に実現できるメニュー項目の実装を行う。

「ファイル」メニューの「上書き保存」「名前を付けて保存」「プロパティ」および「編集」メニューの「このページの検索」機能はIWebBrowser2::ExecWBを呼び出すことで実行できる。

「ファイル」メニューの「送信」にある「ショートカットをデスクトップへ」はIWebBrowser2からIShellBrowserを取り出してIOleCommandTarget::Execにより実行できる。

これらの実装をCIEUtilityに追加する。
	//■追加
	bool	Save(void)
	{
		if(_pIWebBrowser2 == NULL)
			return	false;
		return	SUCCEEDED(_pIWebBrowser2->ExecWB(OLECMDID_SAVE,MSOCMDEXECOPT_DODEFAULT,NULL,NULL)) ? true : false;
	}

	//■追加
	//mhtには対応しない
	bool	SaveAs(void)
	{
		CComVariant	vIn(L"");			//これでファイル名指定

		if(_pIWebBrowser2 == NULL)
			return	false;
		return	SUCCEEDED(_pIWebBrowser2->ExecWB(OLECMDID_SAVEAS,MSOCMDEXECOPT_DODEFAULT,&vIn,NULL)) ? true : false;
	}

	//■追加
	bool	ShowProperty(void)
	{
		if(_pIWebBrowser2 == NULL)
			return	false;
		return	SUCCEEDED(_pIWebBrowser2->ExecWB(OLECMDID_PROPERTIES,OLECMDEXECOPT_PROMPTUSER,NULL,NULL)) ? true : false;
	}

	//■追加
	bool	ShowFind(void)
	{
		if(_pIWebBrowser2 == NULL)
			return	false;
		return	SUCCEEDED(_pIWebBrowser2->ExecWB(OLECMDID_FIND,OLECMDEXECOPT_PROMPTUSER,NULL,NULL)) ? true : false;
	}

	//■追加
	HRESULT	ExecExplorer(IWebBrowser2* pIWebBrowser2,DWORD nCmdID,DWORD nCmdExecOpt,VARIANTARG *pvaIn,VARIANTARG *pvaOut)
	{
		HRESULT		hr;
		CComPtr<IShellBrowser>		pIShellBrowser;

		if(pIWebBrowser2 == NULL)
			return	E_FAIL;

		hr = IUnknown_QueryService(pIWebBrowser2,SID_STopLevelBrowser,IID_IShellBrowser,(void**)&pIShellBrowser);
		if(SUCCEEDED(hr))
			hr = IUnknown_Exec(pIShellBrowser,&CGID_Explorer,nCmdID,nCmdExecOpt,pvaIn,pvaOut);

		return	hr;
	}

	//■追加
	bool	CreateShortcut(void)
	{
		//定数はshlobj.hから
		#ifndef	SBCMDID_CREATESHORTCUT
			#define SBCMDID_CREATESHORTCUT		17
		#endif

		return	SUCCEEDED(ExecExplorer(_pIWebBrowser2,SBCMDID_CREATESHORTCUT,OLECMDEXECOPT_PROMPTUSER,NULL,NULL)) ? true : false;
	}

tabbrowser153.gif そして「MainFrm.h」でメニューが選択されたときに上で実装した関数が呼びだされるようにする。
		COMMAND_ID_HANDLER(ID_EDIT_PASTE, OnFileCommand)
		COMMAND_ID_HANDLER(ID_EDIT_SELECT_ALL, OnFileCommand)
		COMMAND_ID_HANDLER(ID_FILE_SAVE, OnFileCommand)				//■追加
		COMMAND_ID_HANDLER(ID_FILE_SAVE_AS, OnFileCommand)			//■追加
		COMMAND_ID_HANDLER(ID_FILE_CREATE_SHORTCUT, OnFileCommand)	//■追加
		COMMAND_ID_HANDLER(ID_FILE_PROPERTY, OnFileCommand)			//■追加
		COMMAND_ID_HANDLER(ID_EDIT_FIND, OnFileCommand)				//■追加
		COMMAND_RANGE_HANDLER(ID_WINDOW_TABFIRST, ID_WINDOW_TABLAST, OnWindowActivate)
		COMMAND_ID_HANDLER(ID_IE_BACK, OnIECommand)
		COMMAND_ID_HANDLER(ID_IE_NEXT, OnIECommand)
		COMMAND_ID_HANDLER(ID_IE_STOP, OnIECommand)
		COMMAND_ID_HANDLER(ID_IE_REFRESH, OnIECommand)
		COMMAND_ID_HANDLER(ID_IE_ADDFAVORITE, OnIEAddFavorite)
		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 OnFileCommand(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& bHandled)
	{
		CTabBrowser100View*	pView;

		pView = GetActivePageView();
		if(pView == NULL)
		{
			bHandled = FALSE;
			return	0;
		}

		bHandled = TRUE;
		switch(wID)
		{
			///////////////////////
			//■追加ここから
		case	ID_FILE_SAVE:				//上書き保存
			pView->Save();
			break;

		case	ID_FILE_SAVE_AS:			//名前を付けて保存
			pView->SaveAs();
			break;

		case	ID_FILE_CREATE_SHORTCUT:	//デスクトップにリンク作成
			pView->CreateShortcut();
			break;

		case	ID_FILE_PROPERTY:			//プロパティ
			pView->ShowProperty();
			break;

		case	ID_EDIT_FIND:				//検索
			pView->ShowFind();
			break;
			//■追加ここまで
			///////////////////////

		case	ID_EDIT_COPY:				//コピー
			pView->Copy();
			break;

		case	ID_EDIT_CUT:				//切り取り
			pView->Cut();
			break;

		case	ID_EDIT_PASTE:				//貼り付け
			pView->Paste();
			break;

		case	ID_EDIT_SELECT_ALL:			//全てを選択
			pView->SelectAll();
			break;

		case	ID_FILE_PRINT:				//印刷
			pView->PrintOrPreview(true);
			break;

		case	ID_FILE_PRINT_PREVIEW:		//印刷プレビュー
			pView->PrintOrPreview(false);
			break;

		case	ID_FILE_PRINT_SETUP:		//印刷セットアップ
			pView->PrintSetup();
			break;

		default:
			bHandled = FALSE;
			break;
		}

		return	0;
	}

tabbrowser154.gif メニュー項目が無効化されているので、有効化しておく。本来であればコマンドを利用できるときのみ有効にするべきだが、その作業は今後行うことにして今は保留しておく。
		//未実装メニュー項目を全部無効に設定
		{
			UIEnable(ID_FILE_COPY_TAB, FALSE);
			UIEnable(ID_FILE_NEW_WINDOW, FALSE);
			UIEnable(ID_FILE_NEW_SESSION, FALSE);
			UIEnable(ID_FILE_OPEN, FALSE);
			UIEnable(ID_FILE_EDIT, FALSE);
//			UIEnable(ID_FILE_SAVE, FALSE);				//■コメントアウト 有効/無効設定必要
//			UIEnable(ID_FILE_SAVE_AS, FALSE);			//■コメントアウト 有効/無効設定必要
			UIEnable(ID_FILE_SEND_PAGE, FALSE);
			UIEnable(ID_FILE_SEND_LINK, FALSE);
//			UIEnable(ID_FILE_CREATE_SHORTCUT, FALSE);	//■コメントアウト 有効/無効設定必要
			UIEnable(ID_FILE_INPORT_EXPORT, FALSE);
//			UIEnable(ID_FILE_PROPERTY, FALSE);			//■コメントアウト 有効/無効設定必要
			UIEnable(ID_FILE_OFFLINE, FALSE);
//			UIEnable(ID_EDIT_FIND, FALSE);				//■コメントアウト 有効/無効設定必要
			UIEnable(ID_VIEW_FIXED, FALSE);
			UIEnable(ID_VIEW_QUICKTAB, FALSE);
			UIEnable(ID_VIEW_FAVORITE, FALSE);
			UIEnable(ID_VIEW_HISTORY, FALSE);
			UIEnable(ID_VIEW_FEED, FALSE);

tabbrowser155.gif
これで実行すると今回実装したメニューが利用できるようになった。

試してみると「保存」コマンドはInternet Explorer 8では.mhtファイルへの保存に対応しているが、今回の実装ではうまく動かない。ページが完全に読み込み終わる前にメニューを選択するとmhtファイルの選択欄が現れるが、ページが読み込まれた後にメニューを選択すると選択肢が消えてしまう。IE8だからなのかはわからないがどうも挙動がおかしい。それらの調査は今後行うことにして今は保留しておく。

次回はメニュー関連からは少し離れてステータスバーを少し見直す。

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

第36回 キーボードショートカットを設定する (タブブラウザーを作る)

tabbrowser148.gif
前回はタブブラウザーに(機能は実装していないものの)メニュー項目を大量追加した。今回はメニューに割り当てられているショートカットキーの設定、未実装項目のグレーアウトをする。

キーボードショートカットの設定はリソースのアクセラレーターで行う。今回も数が多いのでリソースファイルを直接編集することにした。ソリューションエクスプローラーで「TabBrowser100.rc」を右クリックして現われるメニューから「コードの表示」を選択する。

tabbrowser149.gif リソースファイルが開いたら、「Accelerator」セクションにある定義をメニューに即したものに書き換える。今回は以下のようにした。
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//

IDR_MAINFRAME ACCELERATORS 
BEGIN
    "T",            ID_FILE_NEW,                VIRTKEY, CONTROL
    "K",            ID_FILE_COPY_TAB,           VIRTKEY, CONTROL
    "N",            ID_FILE_NEW_WINDOW,         VIRTKEY, CONTROL
    "O",            ID_FILE_OPEN,               VIRTKEY, CONTROL
    "S",            ID_FILE_SAVE,               VIRTKEY, CONTROL
    "W",            ID_WINDOW_CLOSE,            VIRTKEY, CONTROL
    "P",            ID_FILE_PRINT,              VIRTKEY, CONTROL
    "X",            ID_EDIT_CUT,                VIRTKEY, CONTROL
    "C",            ID_EDIT_COPY,               VIRTKEY, CONTROL
    "V",            ID_EDIT_PASTE,              VIRTKEY, CONTROL
    "A",            ID_EDIT_SELECT_ALL,         VIRTKEY, CONTROL
    "F",            ID_EDIT_FIND,               VIRTKEY, CONTROL
    "Q",            ID_VIEW_QUICKTAB,           VIRTKEY, CONTROL
    "I",            ID_VIEW_FAVORITE,           VIRTKEY, CONTROL, SHIFT
    "H",            ID_VIEW_HISTORY,            VIRTKEY, CONTROL, SHIFT
    "J",            ID_VIEW_FEED,               VIRTKEY, CONTROL, SHIFT
    VK_ESCAPE,      ID_IE_STOP,                 VIRTKEY
    VK_F5,          ID_IE_REFRESH,              VIRTKEY
    VK_ADD,         ID_VIEW_ZOOM_PLUS,          VIRTKEY, CONTROL
    VK_SUBTRACT,    ID_VIEW_ZOOM_MINUS,         VIRTKEY, CONTROL
    VK_F7,          ID_VIEW_CURSOR_BROWSE,      VIRTKEY
    VK_F11,         ID_VIEW_FULL_SCREEN,        VIRTKEY
    VK_F4,          ID_WINDOW_CLOSE,            VIRTKEY, CONTROL
    VK_DELETE,      ID_TOOL_CLEAR_HISTORY,      VIRTKEY, CONTROL, SHIFT
    "P",            ID_TOOL_INPRIVATE_BROWSE,   VIRTKEY, CONTROL, SHIFT
    "F",            ID_TOOL_INPRIVATE_FILTER,   VIRTKEY, CONTROL, SHIFT
    VK_F12,         ID_TOOL_DEVELOP,            VIRTKEY
    VK_BACK,        ID_EDIT_UNDO,           VIRTKEY, ALT
    VK_DELETE,      ID_EDIT_CUT,            VIRTKEY, SHIFT
    VK_INSERT,      ID_EDIT_COPY,           VIRTKEY, CONTROL
    VK_INSERT,      ID_EDIT_PASTE,          VIRTKEY, SHIFT
    VK_F6,          ID_NEXT_PANE,           VIRTKEY 
    VK_F6,          ID_PREV_PANE,           VIRTKEY, SHIFT
END

tabbrowser150.gif
さらに追加したメニュー項目を選択できないようにグレー表示にする。

「MainFrm.h」を開き、追加したメニュー項目をUIアイテムとして登録、無効化する。向こうにするだけなので本来ならOnCreateでUIEnable設定するべきだが、今後修正が楽なように今回はOnIdleに配置した。
	virtual BOOL OnIdle()
	{
		CTabBrowser100View*	pView;

		pView = GetActivePageView();

		//「戻る」「進む」ボタンの状態設定
		{
			bool	bBack = false;
			bool	bNext = false;

			if(pView)
				pView->IsButtonEnable(bBack,bNext);

			UIEnable(ID_IE_BACK,bBack ? TRUE : FALSE);
			UIEnable(ID_IE_NEXT,bNext ? TRUE : FALSE);
		}

		//「編集」メニュー項目更新
		{
			bool	bCopy		= false;
			bool	bCut		= false;
			bool	bPaste		= false;
			bool	bSelectAll	= false;

			if(pView)
				pView->IsEnable_EditCommand(bCopy,bCut,bPaste,bSelectAll);

			UIEnable(ID_EDIT_COPY		,bCopy ? TRUE : FALSE);
			UIEnable(ID_EDIT_CUT		,bCut ? TRUE : FALSE);
			UIEnable(ID_EDIT_PASTE		,bPaste ? TRUE : FALSE);
			UIEnable(ID_EDIT_SELECT_ALL	,bSelectAll ? TRUE : FALSE);
		}


		//■追加 未実装メニュー項目を全部無効に設定
		{
			UIEnable(ID_FILE_COPY_TAB, FALSE);
			UIEnable(ID_FILE_NEW_WINDOW, FALSE);
			UIEnable(ID_FILE_NEW_SESSION, FALSE);
			UIEnable(ID_FILE_OPEN, FALSE);
			UIEnable(ID_FILE_EDIT, FALSE);
			UIEnable(ID_FILE_SAVE, FALSE);
			UIEnable(ID_FILE_SAVE_AS, FALSE);
			UIEnable(ID_FILE_SEND_PAGE, FALSE);
			UIEnable(ID_FILE_SEND_LINK, FALSE);
			UIEnable(ID_FILE_CREATE_SHORTCUT, FALSE);
			UIEnable(ID_FILE_INPORT_EXPORT, FALSE);
			UIEnable(ID_FILE_PROPERTY, FALSE);
			UIEnable(ID_FILE_OFFLINE, FALSE);
			UIEnable(ID_EDIT_FIND, FALSE);
			UIEnable(ID_VIEW_FIXED, FALSE);
			UIEnable(ID_VIEW_QUICKTAB, FALSE);
			UIEnable(ID_VIEW_FAVORITE, FALSE);
			UIEnable(ID_VIEW_HISTORY, FALSE);
			UIEnable(ID_VIEW_FEED, FALSE);
			UIEnable(ID_VIEW_GO, FALSE);
			UIEnable(ID_VIEW_ZOOM_PLUS, FALSE);
			UIEnable(ID_VIEW_ZOOM_MINUS, FALSE);
			UIEnable(ID_VIEW_ZOOM_400, FALSE);
			UIEnable(ID_VIEW_ZOOM_200, FALSE);
			UIEnable(ID_VIEW_ZOOM_150, FALSE);
			UIEnable(ID_VIEW_ZOOM_125, FALSE);
			UIEnable(ID_VIEW_ZOOM_100, FALSE);
			UIEnable(ID_VIEW_ZOOM_75, FALSE);
			UIEnable(ID_VIEW_ZOOM_50, FALSE);
			UIEnable(ID_VIEW_ZOOM_CUSTOM, FALSE);
			UIEnable(ID_VIEW_CHAR_MAX, FALSE);
			UIEnable(ID_VIEW_CHAR_LARGE, FALSE);
			UIEnable(ID_VIEW_CHAR_MIDDLE, FALSE);
			UIEnable(ID_VIEW_CHAR_SMALL, FALSE);
			UIEnable(ID_VIEW_CHAR_MIN, FALSE);
			UIEnable(ID_VIEW_ENCODE_AUTO, FALSE);
			UIEnable(ID_VIEW_ENCODE_TO_RIGHT, FALSE);
			UIEnable(ID_VIEW_ENCODE_TO_LEFT, FALSE);
			UIEnable(ID_VIEW_STYLE_NONE, FALSE);
			UIEnable(ID_VIEW_STYLE_DEFAULT, FALSE);
			UIEnable(ID_VIEW_CURSOR_BROWSE, FALSE);
			UIEnable(ID_VIEW_SOURCE, FALSE);
			UIEnable(ID_VIEW_SECURITY_REPORT, FALSE);
			UIEnable(ID_VIEW_DOMAIN, FALSE);
			UIEnable(ID_VIEW_PRIVACY_POLICY, FALSE);
			UIEnable(ID_VIEW_FULL_SCREEN, FALSE);
			UIEnable(ID_FAVORITE_ADD_TO_BAR, FALSE);
			UIEnable(ID_FAVORITE_ADD_ALLTAB, FALSE);
			UIEnable(ID_TOOL_CLEAR_HISTORY, FALSE);
			UIEnable(ID_TOOL_INPRIVATE_BROWSE, FALSE);
			UIEnable(ID_TOOL_CHECK_NETSTAT, FALSE);
			UIEnable(ID_TOOL_OPEN_LAST_SESSION, FALSE);
			UIEnable(ID_TOOL_INPRIVATE_FILTER, FALSE);
			UIEnable(ID_TOOL_INPRIVATE_FILTER_OPTION, FALSE);
			UIEnable(ID_TOOL_POPUP_DISABLE, FALSE);
			UIEnable(ID_TOOL_POPUP_OPTION, FALSE);
			UIEnable(ID_TOOL_CHECK_THIS_SITE, FALSE);
			UIEnable(ID_TOOL_SMARTSCREEN_DISABLE, FALSE);
			UIEnable(ID_TOOL_SEND_REPORT, FALSE);
			UIEnable(ID_TOOL_MANAGE_ADDON, FALSE);
			UIEnable(ID_TOOL_FEED_ADD, FALSE);
			UIEnable(ID_TOOL_FEED_FIND, FALSE);
			UIEnable(ID_TOOL_WINDOWS_UPDATE, FALSE);
			UIEnable(ID_TOOL_DEVELOP, FALSE);
			UIEnable(ID_TOOL_INTERNET_OPTION, FALSE);
		}

		UIUpdateToolBar();
		return FALSE;
	}

	BEGIN_UPDATE_UI_MAP(CMainFrame)
		UPDATE_ELEMENT(ID_VIEW_TOOLBAR, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_STATUS_BAR, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_IE_BACK, UPDUI_TOOLBAR)
		UPDATE_ELEMENT(ID_IE_NEXT, UPDUI_TOOLBAR)
		UPDATE_ELEMENT(ID_EDIT_COPY, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_EDIT_CUT, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_EDIT_PASTE, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_EDIT_SELECT_ALL, UPDUI_TOOLBAR | UPDUI_MENUPOPUP)
		//■以下追加
		UPDATE_ELEMENT(ID_FILE_COPY_TAB, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_FILE_NEW_WINDOW, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_FILE_NEW_SESSION, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_FILE_OPEN, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_FILE_EDIT, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_FILE_SAVE, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_FILE_SAVE_AS, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_FILE_SEND_PAGE, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_FILE_SEND_LINK, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_FILE_CREATE_SHORTCUT, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_FILE_INPORT_EXPORT, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_FILE_PROPERTY, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_FILE_OFFLINE, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_EDIT_FIND, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_FIXED, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_QUICKTAB, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_FAVORITE, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_HISTORY, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_FEED, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_GO, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_ZOOM_PLUS, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_ZOOM_MINUS, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_ZOOM_400, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_ZOOM_200, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_ZOOM_150, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_ZOOM_125, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_ZOOM_100, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_ZOOM_75, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_ZOOM_50, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_ZOOM_CUSTOM, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_CHAR_MAX, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_CHAR_LARGE, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_CHAR_MIDDLE, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_CHAR_SMALL, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_CHAR_MIN, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_ENCODE_AUTO, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_ENCODE_TO_RIGHT, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_ENCODE_TO_LEFT, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_STYLE_NONE, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_STYLE_DEFAULT, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_CURSOR_BROWSE, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_SOURCE, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_SECURITY_REPORT, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_DOMAIN, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_PRIVACY_POLICY, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_VIEW_FULL_SCREEN, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_FAVORITE_ADD_TO_BAR, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_FAVORITE_ADD_ALLTAB, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_TOOL_CLEAR_HISTORY, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_TOOL_INPRIVATE_BROWSE, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_TOOL_CHECK_NETSTAT, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_TOOL_OPEN_LAST_SESSION, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_TOOL_INPRIVATE_FILTER, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_TOOL_INPRIVATE_FILTER_OPTION, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_TOOL_POPUP_DISABLE, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_TOOL_POPUP_OPTION, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_TOOL_CHECK_THIS_SITE, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_TOOL_SMARTSCREEN_DISABLE, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_TOOL_SEND_REPORT, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_TOOL_MANAGE_ADDON, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_TOOL_FEED_ADD, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_TOOL_FEED_FIND, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_TOOL_WINDOWS_UPDATE, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_TOOL_DEVELOP, UPDUI_MENUPOPUP)
		UPDATE_ELEMENT(ID_TOOL_INTERNET_OPTION, UPDUI_MENUPOPUP)
	END_UPDATE_UI_MAP()

tabbrowser151.gif
これでビルド/実行すると未実装なメニュー項目がグレーアウトし、選択できなくなった。

本当はさらにステータスバーへのメッセージ表示やTIPSが表示されるように、ストリングリソースの編集も行うべきだが、数が多く面倒なので保留しておく。

次回は「ファイル」メニューの「プロパティ」などいくつかのメニュー項目を実装する。

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

第35回 Internet Exolorer風にメニュー項目を追加する (タブブラウザーを作る)

tabbrowser142.gif
今回はタブブラウザのメニューにInternet Explorerと同じような項目を追加する。項目を作るだけで実際に処理を実装するのはまだまだ先だ。

今回は一度にたくさんのメニュー項目を追加することになる。リソースエディタで1つずつ入力してもいいが、数が多いときは大変な作業になる。そこでrcファイルを直接編集して項目を追加する。

ソリューションエクスプローラーで「TabBrowser100.rc」の上で右クリックして現われるメニューから「コードの表示」を選択する。

tabbrowser143.gif するとリソースエディタが開かずに、直接rcファイルの中身が表示される。ここでメニューの項目をInternet Explorerと同じようなものに書き換える。今回はInternet Explorer 8と同じような配置になるようにした。
IDR_MAINFRAME MENU 
BEGIN
    POPUP "ファイル(&F)"
    BEGIN
        MENUITEM "新しいタブ(&T)\tCtrl+T",           ID_FILE_NEW
        MENUITEM "タブを複製(&B)\tCtrl+K",           ID_FILE_COPY_TAB
        MENUITEM "新規ウインドウ(&N)\tCtrl+N",         ID_FILE_NEW_WINDOW
        MENUITEM "新規セッション(&I)",                 ID_FILE_NEW_SESSION
        MENUITEM "開く(&O)...\tCtrl+O",           ID_FILE_OPEN
        MENUITEM "編集(&D)",                      ID_FILE_EDIT
        MENUITEM "上書き保存(&S)\tCtrl+S",           ID_FILE_SAVE
        MENUITEM "名前を付けて保存(&A)...",             ID_FILE_SAVE_AS
        MENUITEM "タブを閉じる(&C)\tCtrl+W",          ID_WINDOW_CLOSE
        MENUITEM SEPARATOR
        MENUITEM "ページ設定(&U)...",                ID_FILE_PRINT_SETUP
        MENUITEM "印刷(&P)...\tCtrl+P",           ID_FILE_PRINT
        MENUITEM "プレビュー(&V)...",                ID_FILE_PRINT_PREVIEW
        MENUITEM SEPARATOR
        POPUP "送信(&E)"
        BEGIN
            MENUITEM "ページを電子メールで(&P)...",           ID_FILE_SEND_PAGE
            MENUITEM "リンクを電子メールで(&L)...",           ID_FILE_SEND_LINK
            MENUITEM "ショートカットをデスクトップへ(&S)",         ID_FILE_CREATE_SHORTCUT
        END
        MENUITEM "インポートおよびエクスポート(&I)...",       ID_FILE_INPORT_EXPORT
        MENUITEM SEPARATOR
        MENUITEM "プロパティ(&R)",                   ID_FILE_PROPERTY
        MENUITEM "オフライン作業(&W)",                 ID_FILE_OFFLINE
        MENUITEM "終了(&X)",                      ID_APP_EXIT
    END
    POPUP "編集(&E)"
    BEGIN
        MENUITEM "切り取り(&T)\tCtrl+X",            ID_EDIT_CUT
        MENUITEM "コピー(&C)\tCtrl+C",             ID_EDIT_COPY
        MENUITEM "貼り付け(&P)\tCtrl+V",            ID_EDIT_PASTE
        MENUITEM SEPARATOR
        MENUITEM "全て選択(&A)\tCtrl+A",            ID_EDIT_SELECT_ALL
        MENUITEM SEPARATOR
        MENUITEM "このページの検索(&F)...\tCtrl+F",     ID_EDIT_FIND
    END
    POPUP "表示(&V)"
    BEGIN
        POPUP "ツール バー(&T)"
        BEGIN
            MENUITEM "ツール バー(&T)",                  ID_VIEW_TOOLBAR
            MENUITEM SEPARATOR
            MENUITEM "ツール バーを固定する(&L)",             ID_VIEW_FIXED
        END
        MENUITEM "クイックタブ(&Q)\tCtrl+Q",          ID_VIEW_QUICKTAB
        POPUP "エクスプローラー バー(&E)"
        BEGIN
            MENUITEM "お気に入り(&F)\tCtrl+Shift+I",     ID_VIEW_FAVORITE
            MENUITEM "履歴(&H)\tCtrl+Shift+H",        ID_VIEW_HISTORY
            MENUITEM "フィード(&D)\tCtrl+Shift+J",      ID_VIEW_FEED
        END
        MENUITEM "ステータス バー(&S)",                ID_VIEW_STATUS_BAR
        MENUITEM SEPARATOR
        MENUITEM "移動(&G)",                      ID_VIEW_GO
        MENUITEM "中止(&P)\tEsc",                 ID_IE_STOP
        MENUITEM "最新の状態に更新(&R)\tF5",            ID_IE_REFRESH
        MENUITEM SEPARATOR
        POPUP "拡大(&Z)"
        BEGIN
            MENUITEM "拡大\tCtrl +",                  ID_VIEW_ZOOM_PLUS
            MENUITEM "縮小\tCtrl -",                  ID_VIEW_ZOOM_MINUS
            MENUITEM SEPARATOR
            MENUITEM "400%",                        ID_VIEW_ZOOM_400
            MENUITEM "200%",                        ID_VIEW_ZOOM_200
            MENUITEM "150%",                        ID_VIEW_ZOOM_150
            MENUITEM "125%",                        ID_VIEW_ZOOM_125
            MENUITEM "100%",                        ID_VIEW_ZOOM_100
            MENUITEM " 75%",                        ID_VIEW_ZOOM_75
            MENUITEM " 50%",                        ID_VIEW_ZOOM_50
            MENUITEM SEPARATOR
            MENUITEM " カスタム...",                        ID_VIEW_ZOOM_CUSTOM
        END
        POPUP "文字の大きさ(&X)"
        BEGIN
            MENUITEM "最大(&G)",                      ID_VIEW_CHAR_MAX
            MENUITEM "大(&L)",                       ID_VIEW_CHAR_LARGE
            MENUITEM "中(&M)",                       ID_VIEW_CHAR_MIDDLE
            MENUITEM "小(&S)",                       ID_VIEW_CHAR_SMALL
            MENUITEM "最小(&A)",                      ID_VIEW_CHAR_MIN
        END
        POPUP "エンコード(&D)"
        BEGIN
            MENUITEM "自動選択",                        ID_VIEW_ENCODE_AUTO
            MENUITEM SEPARATOR
            MENUITEM SEPARATOR
            MENUITEM "ドキュメントの方向 - 左から右",            ID_VIEW_ENCODE_TO_RIGHT
            MENUITEM "ドキュメントの方向 - 右から左",            ID_VIEW_ENCODE_TO_LEFT
        END
        POPUP "スタイル(&Y)"
        BEGIN
            MENUITEM "スタイルなし(&N)",                  ID_VIEW_STYLE_NONE
            MENUITEM "既定のスタイル(&D)",                 ID_VIEW_STYLE_DEFAULT
        END
        MENUITEM "カーソル ブラウズ(&B)\tF7",           ID_VIEW_CURSOR_BROWSE
        MENUITEM SEPARATOR
        MENUITEM "ソース(&C)",                     ID_VIEW_SOURCE
        MENUITEM "セキュリティ報告(&S)",                ID_VIEW_SECURITY_REPORT
        MENUITEM "インターナショナル Web サイト アドレス(&I)",  ID_VIEW_DOMAIN
        MENUITEM "Web ページのプライバシー ポリシー(&V)...",  ID_VIEW_PRIVACY_POLICY
        MENUITEM "全画面表示(&F)\tF11",              ID_VIEW_FULL_SCREEN
    END
    POPUP "ウインドウ(&W)"
    BEGIN
        MENUITEM "閉じる(&C)\tCtrl+F4",            ID_WINDOW_CLOSE
        MENUITEM "全て閉じる(&A)",                   ID_WINDOW_CLOSE_ALL
    END
    POPUP "お気に入り(&A)"
    BEGIN
        MENUITEM "dummy",                       ID_FAVORITE_DUMMY
        MENUITEM "お気に入りに追加(&A)...",             ID_IE_ADDFAVORITE
        MENUITEM "お気に入りバーに追加(&B)",              ID_FAVORITE_ADD_TO_BAR
        MENUITEM "現在の全てのタブをお気に入りに追加(&T)...",    ID_FAVORITE_ADD_ALLTAB
        MENUITEM SEPARATOR
        MENUITEM "お気に入りの整理(&O)...",             ID_IE_ORGANIZE_FAVORITE
        MENUITEM SEPARATOR
    END
    POPUP "ツール(&T)"
    BEGIN
        MENUITEM "閲覧の履歴の削除(&D)...\tCtrl+Shift+Del", ID_TOOL_CLEAR_HISTORY
        MENUITEM "InPrivate ブラウズ(&I)\tCtrl+Shift+P", ID_TOOL_INPRIVATE_BROWSE
        MENUITEM "接続の問題を診断(&C)...",             ID_TOOL_CHECK_NETSTAT
        MENUITEM "最終閲覧セッションを再度開く(&S)",          ID_TOOL_OPEN_LAST_SESSION
        MENUITEM SEPARATOR
        MENUITEM "InPrivate フィルター\tCtrl+Shift+F", ID_TOOL_INPRIVATE_FILTER
        MENUITEM "InPrivate フィルター設定(&S)",       ID_TOOL_INPRIVATE_FILTER_OPTION
        MENUITEM SEPARATOR
        POPUP "ポップアップ ブロック(&P)"
        BEGIN
            MENUITEM "無効にする(&B)",                   ID_TOOL_POPUP_DISABLE
            MENUITEM "設定(&P)...",                   ID_TOOL_POPUP_OPTION
        END
        POPUP "SmartScreen フィルター機能(&T)"
        BEGIN
            MENUITEM "この Web サイトを確認する(&C)",         ID_TOOL_CHECK_THIS_SITE
            MENUITEM "SmartScreen フィルター機能を無効にする(&F)...", ID_TOOL_SMARTSCREEN_DISABLE
            MENUITEM "安全でない Web サイトを報告する(&R)",      ID_TOOL_SEND_REPORT
        END
        MENUITEM "アドオンの管理(&A)",                 ID_TOOL_MANAGE_ADDON
        MENUITEM SEPARATOR
        MENUITEM "このフィードの購読(&F)...",            ID_TOOL_FEED_ADD
        MENUITEM "フィード探索(&E)...",               ID_TOOL_FEED_FIND
        MENUITEM "Windows Update(&U)",          ID_TOOL_WINDOWS_UPDATE
        MENUITEM SEPARATOR
        MENUITEM "開発者ツール(&L)\tF12",             ID_TOOL_DEVELOP
        MENUITEM SEPARATOR
        MENUITEM "インターネット オプション(&O)",           ID_TOOL_INTERNET_OPTION
    END
    POPUP "ヘルプ(&H)"
    BEGIN
        MENUITEM "バージョン情報 TabBrowser100(&A)...", ID_APP_ABOUT
    END
END

tabbrowser144.gif 次に新しいメニュー用のIDを定義するために「resource.h」を開く。実際にIDを追加する前に、まず使われていない不要なIDを削除しておこう。
#define IDD_ABOUTBOX                    100
#define IDR_MAINFRAME                   128
#define IDM_TAB                         201
#define ID_WINDOW_CLOSE                 32772
#define ID_WINDOW_CLOSE_ALL             32773
#define ID_IE_BACK                      32775
#define ID_IE_NEXT                      32776
#define ID_IE_STOP                      32777
#define ID_IE_REFRESH                   32778
//#define ID_32779                        32779		//■削除
//#define ID_32780                        32780		//■削除
//#define ID_32781                        32781		//■削除
#define ID_FAVORITE_DUMMY               32782
//#define ID_32783                        32783		//■削除
//#define ID_32784                        32784		//■削除
#define ID_IE_ORGANIZE_FAVORITE         32785
#define ID_IE_ADDFAVORITE               32786
//#define ID_BUTTON32787                  32787		//■削除
#define ID_FAVORITE_FIRST               34000
#define ID_FAVORITE_LAST                54000

tabbrowser145.gif そして次に新しいIDの定義を追加する。
#define	ID_FILE_COPY_TAB					32787
#define	ID_FILE_NEW_WINDOW					32788
#define	ID_FILE_NEW_SESSION					32789
#define	ID_FILE_EDIT						32790
#define	ID_FILE_SEND_PAGE					32791
#define	ID_FILE_SEND_LINK					32792
#define	ID_FILE_CREATE_SHORTCUT				32793
#define	ID_FILE_INPORT_EXPORT				32794
#define	ID_FILE_PROPERTY					32795
#define	ID_FILE_OFFLINE						32796
#define	ID_VIEW_FIXED						32797
#define	ID_VIEW_QUICKTAB					32798
#define	ID_VIEW_FAVORITE					32799
#define	ID_VIEW_HISTORY						32800
#define	ID_VIEW_FEED						32801
#define	ID_VIEW_GO							32802
#define	ID_VIEW_ZOOM_PLUS					32803
#define	ID_VIEW_ZOOM_MINUS					32804
#define	ID_VIEW_ZOOM_400					32805
#define	ID_VIEW_ZOOM_200					32806
#define	ID_VIEW_ZOOM_150					32807
#define	ID_VIEW_ZOOM_125					32808
#define	ID_VIEW_ZOOM_100					32809
#define	ID_VIEW_ZOOM_75						32810
#define	ID_VIEW_ZOOM_50						32811
#define	ID_VIEW_ZOOM_CUSTOM					32812
#define	ID_VIEW_CHAR_MAX					32813
#define	ID_VIEW_CHAR_LARGE					32814
#define	ID_VIEW_CHAR_MIDDLE					32815
#define	ID_VIEW_CHAR_SMALL					32816
#define	ID_VIEW_CHAR_MIN					32817
#define	ID_VIEW_ENCODE_AUTO					32818
#define	ID_VIEW_ENCODE_TO_RIGHT				32819
#define	ID_VIEW_ENCODE_TO_LEFT				32820
#define	ID_VIEW_STYLE_NONE					32821
#define	ID_VIEW_STYLE_DEFAULT				32822
#define	ID_VIEW_CURSOR_BROWSE				32823
#define	ID_VIEW_SOURCE						32824
#define	ID_VIEW_SECURITY_REPORT				32825
#define	ID_VIEW_DOMAIN						32826
#define	ID_VIEW_PRIVACY_POLICY				32827
#define	ID_VIEW_FULL_SCREEN					32828
#define	ID_FAVORITE_ADD_TO_BAR				32829
#define	ID_FAVORITE_ADD_ALLTAB				32830
#define	ID_TOOL_CLEAR_HISTORY				32831
#define	ID_TOOL_INPRIVATE_BROWSE			32832
#define	ID_TOOL_CHECK_NETSTAT				32833
#define	ID_TOOL_OPEN_LAST_SESSION			32834
#define	ID_TOOL_INPRIVATE_FILTER			32835
#define	ID_TOOL_INPRIVATE_FILTER_OPTION		32836
#define	ID_TOOL_POPUP_DISABLE				32837
#define	ID_TOOL_POPUP_OPTION				32838
#define	ID_TOOL_CHECK_THIS_SITE				32839
#define	ID_TOOL_SMARTSCREEN_DISABLE			32840
#define	ID_TOOL_SEND_REPORT					32841
#define	ID_TOOL_MANAGE_ADDON				32842
#define	ID_TOOL_FEED_ADD					32843
#define	ID_TOOL_FEED_FIND					32844
#define	ID_TOOL_WINDOWS_UPDATE				32845
#define	ID_TOOL_DEVELOP						32846
#define	ID_TOOL_INTERNET_OPTION				32847

tabbrowser146.gif
手動でリソースIDを編集するときに一番気をつけなければいけないのが、APSTUDIO_INVOKEDで囲まれた部分の定義だ。

ここにはリソースエディタで新しくIDを作るときに、次の新しいIDで利用する番号が保存されている。ここの編集を忘れると、違う名前で同じ番号のIDがリソースエディタによって生成されてしまう。

新しく生成したIDのうちの最大の値よりも1つ大きい値を今回の場合は「_APS_NEXT_COMMAND_VALUE」を「32848」として定義しておく。
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        202
#define _APS_NEXT_COMMAND_VALUE         32848
#define _APS_NEXT_CONTROL_VALUE         1000
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

tabbrowser147.gif
これでビルド/実行すると無事にメニュー項目が増えた。

今回のメニュー項目の追加では、キーボードショートカットを無視した。次回は今回追加したメニュー項目のキーボードショートカットを設定する。

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

前の10件 10  11  12  13  14  15  16  17  18  19  20