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

記事一覧

第54回 「Googleツールバー」を2つ表示する (タブブラウザーを作る)

tabbrowser237.gif
前回はビューウインドウを中心にIEツールバーを複数利用する準備をした。今回はCMainFrame側を中心に修正を行う。

まずIEツールバーの親ウインドウとなるCDummyWndの中身を変更する。「Googleツールバー」以外のIEツールバーにも対応できるように_clsidIDeskBandを用意し、それを取得するための独自メッセージ処理を用意した。

またこれまでリバーのインデックス渡しにバグがあったので、きちんとIDからインデックスを取得して渡すように修正した。
	//■処理内容変更
	class	CDummyWnd	: public CWindowImpl<CDummyWnd>
	{
		IID		_clsidIDeskBand;	//IEツールバーのGUID
	public:
		UINT	_nBandID;			//リバーのID

		CDummyWnd(IID clsidIDeskBand)
		{
			_nBandID = -1;
			_clsidIDeskBand = clsidIDeskBand;
		}

		BEGIN_MSG_MAP(CDummyWnd)
			MESSAGE_HANDLER(WM_DNP_GETRBINDEX, OnDnpRbIndex)
			MESSAGE_HANDLER(WM_DNP_GETCLSID, OnDnpGetClsid)
			MESSAGE_HANDLER(WM_SIZE, OnSize)
		END_MSG_MAP()


		//リバー操作用のINDEX取得
		LRESULT OnDnpRbIndex(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
		{
			UINT*	pnIndex = (UINT*)wParam;

			if(pnIndex)
				*pnIndex = GetRebarIndex();

			return	0;
		}

		LRESULT OnDnpGetClsid(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
		{
			IID*	piid = (IID*)wParam;

			if(piid)
				*piid = _clsidIDeskBand;

			return	0;
		}


		UINT	GetRebarIndex(void)
		{
			UINT	nIndex = -1;

			if(_nBandID == -1 || IsWindow() == FALSE)
				return	nIndex;

			nIndex = ::SendMessage(::GetParent(m_hWnd),RB_IDTOINDEX,(WPARAM)_nBandID,NULL);

			return	nIndex;
		}


		LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
		{
			bHandled = FALSE;
			if(_nBandID == -1)
				return	0;

			//このウインドウの直下にあるchildウインドウ=IEツールバーをrebarに全体表示する

			CRect	rect;
			HWND	hWnd;

			//rebarサイズ取得
			rect.left	= 0;
			rect.top	= 0;
			rect.right	= LOWORD(lParam);
			rect.bottom	= HIWORD(lParam);

			//子ウインドウを検索してサイズ調節
			hWnd = NULL;
			while(1)
			{
				hWnd = ::FindWindowEx(m_hWnd,hWnd,NULL,NULL);
				if(hWnd == NULL)
					break;

				::MoveWindow(hWnd,rect.left,rect.top,rect.Width(),rect.Height(),FALSE);
			}

			return	0;
		}


		bool	ShowRebar(bool bVisible)
		{
			if(_nBandID == -1 || IsWindow() == FALSE)
				return	false;

			::SendMessage(::GetParent(m_hWnd),RB_SHOWBAND,(WPARAM)GetRebarIndex(),(LPARAM)(bVisible ? TRUE : FALSE));

			return	true;
		}
	};

tabbrowser238.gif そしてCDummyWndをCAtlArrayにより配列化、簡単にCDummyWndを作れるようにAddIEToolbar関数を用意した。
	CAtlArray<CDummyWnd*>	_apwndDummy;		//■変更


	//■追加 処理はOnCreateから移動&変更
	bool	AddIEToolbar(IID clsidIDeskBand)
	{
		CDummyWnd*	pwndDummy;

		pwndDummy = new CDummyWnd(clsidIDeskBand);

		//ダミーウインドウを生成し、リバーに割り当てる。これはIEツールバーに利用
		pwndDummy->Create(m_hWnd,CRect(0,0,500,24),0,WS_CHILD);
		AddSimpleReBarBand(*pwndDummy,0,TRUE);						//1行表示

		//IEツールバー用のrebarのインデックス取得。_wndDummyへ割り当てると同時にrebarを非表示に
		{
			UINT	nCount;

			nCount = (UINT)::SendMessage(m_hWndToolBar,RB_GETBANDCOUNT,NULL,NULL);
			pwndDummy->_nBandID = nCount + ATL_IDW_BAND_FIRST - 1;

			if(m_view.IsWindow() && m_view.GetPageCount())
			{
				//IEツールバーの生成
				//タブの数だけ一気に生成しているから効率が悪すぎる。
				//アクティブになったときに生成すべき
				{
					size_t	i;
					size_t	nSize;
					CTabBrowser100View*	pView;

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

						if(i == m_view.GetActivePage())
							pView->AddIEToolbar(*pwndDummy,true);		// IEツールバー生成
						else
							pView->AddIEToolbar(*pwndDummy,false);		// IEツールバー生成
					}
				}
				pwndDummy->ShowRebar(true);			//表示する
			}
			else
				pwndDummy->ShowRebar(false);		//非表示にする
		}

		_apwndDummy.Add(pwndDummy);

		return	true;
	}

tabbrowser234.gif CDummyWndの配列はnewによる確保にしたので、デストラクタでdeleteしておく。
	//■追加
	~CMainFrame()
	{
		size_t	i;
		size_t	nSize;

		nSize = _apwndDummy.GetCount();
		for(i = 0; i < nSize; i++)
		{
			if(_apwndDummy[i] == NULL)
				continue;
			delete	_apwndDummy[i];
			_apwndDummy[i] = NULL;
		}
	}

tabbrowser235.gif 後はこれまで_wndDummyにアクセスしていた部分を配列に沿ったものに修正する。 まずはリバーの表示/非表示を切り替える処理だ。
	//タブが選択されたときの処理
	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);	//ステータスバー解放
				}
			}

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


		bool		ret;
		CTabBrowser100View*	pView;
		size_t		i;						//■追加
		size_t		nSize;					//■追加
		bool		bVisible;				//■追加

		nSize = _apwndDummy.GetCount();		//■追加

		pView = GetActivePageView();		//アクティブビュー取得
		if(pView == NULL)
			bVisible = false;
		else
			bVisible = true;

		//■変更
		for(i = 0; i < nSize; i++)
		{
			if(_apwndDummy[i])
				_apwndDummy[i]->ShowRebar(bVisible);				//リバー表示
		}

		if(pView == NULL)
			return	0;

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

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

		return	0;
	}

tabbrowser236.gif タブの新規作成処理。今のところ新しいタブは必ずアクティブに開くので、生成時はAddIEToolbarにtrueを渡している。
	//タブの新規作成
	//nPosはタブを追加する場所。nPos<0(もしくはnPos=m_view.GetPageCount())で一番後ろ、
	//そのほかの数値はCTabView::InsertPageにそのまま渡す
	//
	//戻ったポインタは自動削除されるため、deleteの必要なし
	//
	CTabBrowser100View*	CreateNewTab(LPCTSTR pszURL,LPCTSTR pszTitle,int nPos=-1,int nImage=-1)
	{
		bool	ret;
		CTabBrowser100View*	pView;

		pView = new CTabBrowser100View(&m_view);	//タブビューのポインタを渡す
		if(pView == NULL)
			return	NULL;

		//ビューウインドウ生成
		if(pszURL == NULL || *pszURL == NULL)
			pView->Create(m_view, rcDefault, _T("about:blank"), WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_HSCROLL | WS_VSCROLL, 0);
		else
			pView->Create(m_view, rcDefault, pszURL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_HSCROLL | WS_VSCROLL, 0);
		if(pView->IsWindow() == FALSE)
		{
			delete	pView;
			return	NULL;		//ビューウインドウ生成失敗
		}

		//タブにビューを割り当てる
		if(nPos < 0)
			nPos = m_view.GetPageCount();
		if(pszTitle)
			ret = m_view.InsertPage(nPos,pView->m_hWnd,pszTitle,nImage,pView);
		else
			ret = m_view.InsertPage(nPos,pView->m_hWnd,_T(""),nImage,pView);

		if(ret == false)
		{
			delete	pView;
			return	NULL;		//タブへの追加失敗
		}

		//■処理変更
		//IEツールバーの生成
		{
			size_t	i;
			size_t	nSize;

			nSize = _apwndDummy.GetCount();
			for(i = 0; i < nSize; i++)
			{
				if(_apwndDummy[i])
					pView->AddIEToolbar(*_apwndDummy[i],true);		//IEツールバー生成
			}
		}

		return	pView;
	}

tabbrowser239.gif OnCreateで「Googleツールバー」のGUIDを利用してリバーを作る。今回はAddIEToolbarを2度呼ぶことで2つの「Googleツールバー」を表示することにした。
	LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		// コマンドバー ウィンドウの作成
		HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
		// メニューのアタッチ
		m_CmdBar.AttachMenu(GetMenu());
		// コマンドバー画像の読み込み
		m_CmdBar.LoadImages(IDR_MAINFRAME);
		// 以前のメニューの削除
		SetMenu(NULL);

		HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);

		CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
		AddSimpleReBarBand(hWndCmdBar);
		AddSimpleReBarBand(hWndToolBar, NULL, TRUE);

		_wndAddressBar.Create(m_hWnd,CRect(0,0,200,200),0,WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_CLIPCHILDREN,WS_EX_CLIENTEDGE);
		AddSimpleReBarBand(_wndAddressBar,0,TRUE);	//アドレスバーを1列で表示

		//■変更
		//Googleツールバー生成
		{
			GUID	rclsid;
			WCHAR	pszGUID[] = {L"{2318C2B1-4965-11d4-9B18-009027A5CD4F}"};		//GoogleツールバーのGUID

			::CLSIDFromString(pszGUID,&rclsid);

			AddIEToolbar(rclsid);
			AddIEToolbar(rclsid);		//2つ生成
		}


		CreateSimpleStatusBar();

		m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);

		UIAddToolBar(hWndToolBar);
		UISetCheck(ID_VIEW_TOOLBAR, 1);
		UISetCheck(ID_VIEW_STATUS_BAR, 1);

		// メッセージ フィルターおよび画面更新用のオブジェクト登録
		CMessageLoop* pLoop = _Module.GetMessageLoop();
		ATLASSERT(pLoop != NULL);
		pLoop->AddMessageFilter(this);
		pLoop->AddIdleHandler(this);

		CMenuHandle menuMain = m_CmdBar.GetMenu();
		m_view.SetWindowMenu(menuMain.GetSubMenu(WINDOW_MENU_POSITION));

		_cTabImageList.Create(16,16,ILC_COLOR | ILC_MASK,1,10);
		m_view.SetImageList(_cTabImageList);

		return 0;
	}

tabbrowser240.gif 実際のIEツールバー生成処理を担っているビューウインドウ側のCIEToolbarInfoの中で、新しい独自メッセージによりGUIDを取得して利用するようにする。
		//■変更
		//IEツールバーを生成する
		bool	Create(IWebBrowser2* pIWebBrowser2,bool bVisible)
		{
			IID		rclsid = GUID_NULL;

			if(::IsWindow(_hWndRebarIE))
				::SendMessage(_hWndRebarIE,WM_DNP_GETCLSID,(WPARAM)&rclsid,NULL);

			return	CreateIEToolbar(pIWebBrowser2,_hWndRebarIE,&_pIDeskBand,rclsid,bVisible);
		}

tabbrowser241.gif ビューウインドウ側のAddIEToolbarで引数にbVisibleを用意した。
	//■変更
	bool	AddIEToolbar(HWND hWndIERebar,bool bVisible)
	{
		size_t	nIndex;

		nIndex = _aToolbarInfo.Add(CIEToolbarInfo(hWndIERebar));
		_aToolbarInfo[nIndex].Create(_pIWebBrowser2,bVisible);

		return	true;
	}

tabbrowser242.gif 最後に「stdafx.h」内に独自メッセージの定義を追加する。
#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)
#define	WM_DNP_SHOWZONECONFIGURE	(WM_APP + 10)
#define	WM_DNP_GETRBINDEX		(WM_APP + 11)
#define	WM_DNP_GETCLSID			(WM_APP + 12)		//■追加

tabbrowser243.gif
これでビルド/実行すると「Googleツールバー」が2つ表示されるようになった。

次回はInternet Explorerで現在利用可能なツールバーを列挙して使えるようにする。

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

第53回 IE用ツールバーを複数利用するための準備をする (タブブラウザーを作る)

tabbrowser228.gif
これまでInternet Explorer用のツールバーとして「Googleツールバー」のみを固定表示していた。これをこれから数回のステップでInternet Explorerのようにインストールされているツールバーを自由に選択/利用できるできるようにする。

まずはビューウインドウ側を少し修正する。単純にメンバー変数として定義していたHWNDとIDeskBand*をCIEToolbarInfoの中に追い出す。
class CTabBrowser100View : public CWindowImpl<CTabBrowser100View, CAxWindow>
	,public IDispEventImpl<SINKID_EVENTS, CTabBrowser100View, &DIID_DWebBrowserEvents2>
	,public CIEUtility
{
	CTabView*	_pTabView;		//タブビューを保持
//	HWND		_hWndRebarIE;	//■削除 IEツールバー用のリバー

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


	CAtlString	_strLastStatusText;					//最後に送られてきたステータステキストを保管
	CComPtr<IDocHostUIHandler>	_pHideScriptError;
	CIELikeStatusbar			_wndStatusbar;		//ステータスバー
//	CComPtr<IDeskBand>			_pIDeskBand;		//■削除 Googleツールバー

	//■追加
	class	CIEToolbarInfo
	{
	public:
		IDeskBand*	_pIDeskBand;
		HWND		_hWndRebarIE;	//IEツールバー用のリバー


		CIEToolbarInfo()
		{
			_hWndRebarIE	= NULL;
			_pIDeskBand		= NULL;
		}

		CIEToolbarInfo(HWND hWndRebar)
		{
			_hWndRebarIE = hWndRebar;
			_pIDeskBand		= NULL;
		}

		//■CMainFrame内から移動&変更
		//Googleツールバーを生成する
		bool	Create(IWebBrowser2* pIWebBrowser2,bool bVisible)
		{
			GUID	rclsid;
			WCHAR	pszGUID[] = {L"{2318C2B1-4965-11d4-9B18-009027A5CD4F}"};		//GoogleツールバーのGUID

			::CLSIDFromString(pszGUID,&rclsid);

			return	CreateIEToolbar(pIWebBrowser2,_hWndRebarIE,&_pIDeskBand,rclsid,bVisible);
		}

	protected:

		//■CMainFrame内から移動&変更
		//hWndParentはCDummyWnd(Googleツールバーの親となるウインドウハンドル)
		//clsidIDeskBandはGoogleツールバーのCLSIDを指定する
		bool	CreateIEToolbar(IWebBrowser2* pIWebBrowser2,HWND hWndParent,IDeskBand** ppIDeskBand,const IID& clsidIDeskBand,bool bVisible)
		{
			HRESULT	hr;

			if(ppIDeskBand == NULL || pIWebBrowser2 == NULL)
				return	false;
			if(*ppIDeskBand)
			{
				ATLASSERT(0);
				(*ppIDeskBand)->Release();
				*ppIDeskBand = NULL;
			}

			hr = ::CoCreateInstance(clsidIDeskBand,NULL,CLSCTX_INPROC_SERVER,IID_IDeskBand,(void**)ppIDeskBand);
			if(FAILED(hr) || *ppIDeskBand == NULL)
				return	false;

			CComPtr<IObjectWithSite>	pIObjectWithSite;

			(*ppIDeskBand)->QueryInterface(IID_IObjectWithSite,(void**)&pIObjectWithSite);

			//デスクバンドをホスト用クラスに割り当てる
			{
				CComPtr<IIEToolbar>	pIIEToolbar;

				pIIEToolbar = new CComObject<CIEToolbar>;

				pIIEToolbar->put_hwnd(hWndParent);
				if(pIWebBrowser2)
					pIIEToolbar->put_IWebBrowser2(pIWebBrowser2);
				if(pIObjectWithSite)
					hr = pIObjectWithSite->SetSite(pIIEToolbar);

				if(SUCCEEDED(hr) && bVisible)
					hr = (*ppIDeskBand)->ShowDW(TRUE);		//表示
			}

			DESKBANDINFO	sDeskBandInfo;

			//別に必要ないが情報をたくさん取得
			::ZeroMemory(&sDeskBandInfo,sizeof(DESKBANDINFO));
			sDeskBandInfo.dwMask = DBIM_MINSIZE | DBIM_MAXSIZE | DBIM_INTEGRAL | DBIM_ACTUAL | DBIM_TITLE | DBIM_MODEFLAGS | DBIM_BKCOLOR;
			hr = (*ppIDeskBand)->GetBandInfo(0,DBIF_VIEWMODE_NORMAL,&sDeskBandInfo);

			CRect	rect(0,0,1500,sDeskBandInfo.ptMinSize.y);		//サイズの一時設定(後で自動調整)

			//rebar情報の設定
			{
				HWND	hWndRebar;
				UINT	nIndex;

				hWndRebar = ::GetParent(hWndParent);
				nIndex = -1;
				::SendMessage(hWndParent,WM_DNP_GETRBINDEX,(WPARAM)&nIndex,NULL);
				if(nIndex != -1 && hWndRebar)
				{
					REBARBANDINFO	info;

					//MinSizeのみをリバーへ設定。本来ならもっと情報を設定すべき
					::ZeroMemory(&info,sizeof(REBARBANDINFO));
					info.cbSize	= sizeof(REBARBANDINFO);
					info.fMask	= RBBIM_CHILDSIZE;
					::SendMessage(hWndRebar,RB_GETBANDINFO,nIndex,(LPARAM)&info);
					info.cyMinChild	= sDeskBandInfo.ptMinSize.y;
					info.cyChild	= sDeskBandInfo.ptMinSize.y;
					info.cxMinChild	= sDeskBandInfo.ptMinSize.x;
					::SendMessage(hWndRebar,RB_SETBANDINFO,nIndex,(LPARAM)&info);

					//位置調整
					::SendMessage(hWndRebar,RB_GETRECT,nIndex,(LPARAM)&rect);
					::SendMessage(hWndParent,WM_SIZE,SIZE_RESTORED,MAKELPARAM(rect.Width(),rect.Height()));
				}
			}

			return	true;
		}
	};

tabbrowser229.gif 今回はツールバー情報をCAtlArrayとして実装することにした。
	CAtlArray<CIEToolbarInfo>	_aToolbarInfo;		//■追加


public:
	DECLARE_WND_SUPERCLASS(NULL, CAxWindow::GetWndClassName())


	CTabBrowser100View(CTabView* pTabView)		//■変更
	{
		_pTabView = pTabView;
//		_hWndRebarIE = hWndRebarIE;				//■削除
		_bPageError = false;
	}

tabbrowser230.gif
CAtlArrayにより単純にCIEToolbarInfoを配列化しているのでCIEToolbarInfoではCComPtrを使わずにIDeskBand*を利用した。そのためビューウインドウが破棄されるときにReleaseしておく。

さらに配列化したのでOnTabPageChangeでもそれらが呼び出されるように変更する。
	//ビューを閉じるときの処理
	LRESULT OnDestroy(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		bHandled = FALSE;

		if(_pIWebBrowser2)
			Unadvise(_pIWebBrowser2);	//IEからの切断
		_pIWebBrowser2 = NULL;

		//■追加 IEツールバーの削除
		{
			size_t	i;
			size_t	nSize;

			nSize = _aToolbarInfo.GetCount();
			for(i = 0; i < nSize; i++)
			{
				if(_aToolbarInfo[i]._pIDeskBand == NULL)
					continue;

				_aToolbarInfo[i]._pIDeskBand->ShowDW(FALSE);	//非表示
				_aToolbarInfo[i]._pIDeskBand->CloseDW(0);		//終了
				_aToolbarInfo[i]._pIDeskBand->Release();		//リリース
				_aToolbarInfo[i]._pIDeskBand = NULL;
			}
		}

		return	0;
	}



public:



	//■変更
	//メインウインドウから呼ばれる
	//タブの選択変更があったときメインウインドウから呼ばれる
	bool	OnTabPageChange(bool bActivated)
	{
		size_t	i;
		size_t	nSize;

		nSize = _aToolbarInfo.GetCount();
		for(i = 0; i < nSize; i++)
		{
			if(_aToolbarInfo[i]._pIDeskBand == NULL)
				continue;

			if(bActivated)
				_aToolbarInfo[i]._pIDeskBand->ShowDW(TRUE);		//IEツールバーを表示
			else
				_aToolbarInfo[i]._pIDeskBand->ShowDW(FALSE);	//IEツールバーを消す
		}

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

		return	true;
	}

tabbrowser231.gif さらにビューウインドウのCreate内でのGoogleツールバー生成処理を削除し、外部からIE用ツールバーを作成するための関数を追加する。
	//Create関数のオーバーライド。内部でIEの取得、接続などを行う
	HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
			DWORD dwStyle = 0, DWORD dwExStyle = 0,
			_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
	{
		HWND	hWnd;

		hWnd = __super::Create(hWndParent,rect,szWindowName,dwStyle,dwExStyle,MenuOrID,lpCreateParam);
		if(hWnd == NULL)
			return	NULL;			//Create失敗

		QueryControl(&_pIWebBrowser2);		//_pIWebBrowser2にこのビューに関連づいているIEをセットする
		if(_pIWebBrowser2 == NULL)
			return	hWnd;			//WebBrowser取得失敗

		Advise(_pIWebBrowser2);		//IEとの接続


		//jacascriptや画像ダウンロードのコントロール設定
		{
			CComPtr<IOleObject>		pIOleObject;
			CComObject<CAmbientControl>*		pCAmbientControl;
			CComPtr<IAxWinAmbientDispatchEx>	pIAxWinAmbientDispatchEx;

			//ダウンロードコントロールの準備
			CComObject<CAmbientControl>::CreateInstance(&pCAmbientControl);
			if(pCAmbientControl)
				pCAmbientControl->QueryInterface(&_pIAmbientControl);

			//IEコントロールへのセット
			_pIWebBrowser2->QueryInterface(&pIOleObject);
			if(pIOleObject && pCAmbientControl)
				pIOleObject->SetClientSite(pCAmbientControl);

			//デフォルトのダウンロードコントロールを設定
			//本来ならゾーン変化をチェックしてゾーンに応じて決定すべき?
			SetAmbientDownloadControl(DLCTL_DLIMAGES | DLCTL_VIDEOS | DLCTL_BGSOUNDS);
		}


		//■以下削除

		return	hWnd;
	}


	//■追加
	bool	AddIEToolbar(HWND hWndIERebar)
	{
		size_t	nIndex;

		nIndex = _aToolbarInfo.Add(CIEToolbarInfo(hWndIERebar));
		_aToolbarInfo[nIndex].Create(_pIWebBrowser2,true);

		return	true;
	}

tabbrowser232.gif 最後にCMainFrame側でビューを生成するときの処理を変えれば終わりだ。
	//タブの新規作成
	//nPosはタブを追加する場所。nPos<0(もしくはnPos=m_view.GetPageCount())で一番後ろ、
	//そのほかの数値はCTabView::InsertPageにそのまま渡す
	//
	//戻ったポインタは自動削除されるため、deleteの必要なし
	//
	CTabBrowser100View*	CreateNewTab(LPCTSTR pszURL,LPCTSTR pszTitle,int nPos=-1,int nImage=-1)
	{
		bool	ret;
		CTabBrowser100View*	pView;

		pView = new CTabBrowser100View(&m_view);	//■変更 タブビューのポインタを渡す
		if(pView == NULL)
			return	NULL;

		//ビューウインドウ生成
		if(pszURL == NULL || *pszURL == NULL)
			pView->Create(m_view, rcDefault, _T("about:blank"), WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_HSCROLL | WS_VSCROLL, 0);
		else
			pView->Create(m_view, rcDefault, pszURL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_HSCROLL | WS_VSCROLL, 0);
		if(pView->IsWindow() == FALSE)
		{
			delete	pView;
			return	NULL;		//ビューウインドウ生成失敗
		}

		//タブにビューを割り当てる
		if(nPos < 0)
			nPos = m_view.GetPageCount();
		if(pszTitle)
			ret = m_view.InsertPage(nPos,pView->m_hWnd,pszTitle,nImage,pView);
		else
			ret = m_view.InsertPage(nPos,pView->m_hWnd,_T(""),nImage,pView);

		if(ret == false)
		{
			delete	pView;
			return	NULL;		//タブへの追加失敗
		}

		pView->AddIEToolbar(_wndDummy);		//■追加 Googleツールバー生成

		return	pView;
	}

tabbrowser233.gif
これで実行したときの見た目は変わらないが、少しずつ対応できてきた。次回も引き続きIE用ツールバーを複数利用するための実装を準備する。

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

2009年04月11日

第52回 Googleツールバーの表示サイズを自動調整する (タブブラウザーを作る)

tabbrowser224.gif
前回はタブがあるときだけ「Googleツールバー」用のリバーが表示されるようにした。今回はリバーの大きさが「Googleツールバー」に合わせて変わるようにする。

「Googleツールバー」の生成はCMainFrame::OnCreate内で行っていた。それを関数に切り出して呼び出すようにした。生成処理内では前回実装したリバーのIDを取得する処理を使ってDESKBANDINFOの情報をリバーにセットする。
	//Create関数のオーバーライド。内部でIEの取得、接続などを行う
	HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
			DWORD dwStyle = 0, DWORD dwExStyle = 0,
			_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
	{
		HWND	hWnd;

		hWnd = __super::Create(hWndParent,rect,szWindowName,dwStyle,dwExStyle,MenuOrID,lpCreateParam);
		if(hWnd == NULL)
			return	NULL;			//Create失敗

		QueryControl(&_pIWebBrowser2);		//_pIWebBrowser2にこのビューに関連づいているIEをセットする
		if(_pIWebBrowser2 == NULL)
			return	hWnd;			//WebBrowser取得失敗

		Advise(_pIWebBrowser2);		//IEとの接続


		//jacascriptや画像ダウンロードのコントロール設定
		{
			CComPtr<IOleObject>		pIOleObject;
			CComObject<CAmbientControl>*		pCAmbientControl;
			CComPtr<IAxWinAmbientDispatchEx>	pIAxWinAmbientDispatchEx;

			//ダウンロードコントロールの準備
			CComObject<CAmbientControl>::CreateInstance(&pCAmbientControl);
			if(pCAmbientControl)
				pCAmbientControl->QueryInterface(&_pIAmbientControl);

			//IEコントロールへのセット
			_pIWebBrowser2->QueryInterface(&pIOleObject);
			if(pIOleObject && pCAmbientControl)
				pIOleObject->SetClientSite(pCAmbientControl);

			//デフォルトのダウンロードコントロールを設定
			//本来ならゾーン変化をチェックしてゾーンに応じて決定すべき?
			SetAmbientDownloadControl(DLCTL_DLIMAGES | DLCTL_VIDEOS | DLCTL_BGSOUNDS);
		}

		//■変更
		//Googleツールバーを生成する
		{
			GUID	rclsid;
			WCHAR	pszGUID[] = {L"{2318C2B1-4965-11d4-9B18-009027A5CD4F}"};		//GoogleツールバーのGUID

			::CLSIDFromString(pszGUID,&rclsid);

			CreateIEToolbar(_hWndRebarIE,&_pIDeskBand,rclsid);
		}

		return	hWnd;
	}




	//■追加
	//hWndParentはCDummyWnd(Googleツールバーの親となるウインドウハンドル)
	//clsidIDeskBandはGoogleツールバーのCLSIDを指定する
	bool	CreateIEToolbar(HWND hWndParent,IDeskBand** ppIDeskBand,const IID& clsidIDeskBand)
	{
		HRESULT	hr;

		if(ppIDeskBand == NULL)
			return	false;
		if(*ppIDeskBand)
		{
			ATLASSERT(0);
			(*ppIDeskBand)->Release();
			*ppIDeskBand = NULL;
		}

		hr = ::CoCreateInstance(clsidIDeskBand,NULL,CLSCTX_INPROC_SERVER,IID_IDeskBand,(void**)ppIDeskBand);
		if(FAILED(hr) || *ppIDeskBand == NULL)
			return	false;

		CComPtr<IObjectWithSite>	pIObjectWithSite;

		(*ppIDeskBand)->QueryInterface(IID_IObjectWithSite,(void**)&pIObjectWithSite);

		//デスクバンドをホスト用クラスに割り当てる
		{
			CComPtr<IIEToolbar>	pIIEToolbar;

			pIIEToolbar = new CComObject<CIEToolbar>;

			pIIEToolbar->put_hwnd(hWndParent);
			if(_pIWebBrowser2)
				pIIEToolbar->put_IWebBrowser2(_pIWebBrowser2);
			if(pIObjectWithSite)
				hr = pIObjectWithSite->SetSite(pIIEToolbar);

			if(SUCCEEDED(hr))
				hr = (*ppIDeskBand)->ShowDW(TRUE);		//表示
		}

		DESKBANDINFO	sDeskBandInfo;

		//別に必要ないが情報をたくさん取得
		::ZeroMemory(&sDeskBandInfo,sizeof(DESKBANDINFO));
		sDeskBandInfo.dwMask = DBIM_MINSIZE | DBIM_MAXSIZE | DBIM_INTEGRAL | DBIM_ACTUAL | DBIM_TITLE | DBIM_MODEFLAGS | DBIM_BKCOLOR;
		hr = (*ppIDeskBand)->GetBandInfo(0,DBIF_VIEWMODE_NORMAL,&sDeskBandInfo);

		CRect	rect(0,0,1500,sDeskBandInfo.ptMinSize.y);		//サイズの一時設定(後で自動調整)

		//rebar情報の設定
		{
			HWND	hWndRebar;
			UINT	nIndex;

			hWndRebar = ::GetParent(hWndParent);
			nIndex = -1;
			::SendMessage(hWndParent,WM_DNP_GETRBINDEX,(WPARAM)&nIndex,NULL);
			if(nIndex != -1 && hWndRebar)
			{
				REBARBANDINFO	info;

				//MinSizeのみをリバーへ設定。本来ならもっと情報を設定すべき
				::ZeroMemory(&info,sizeof(REBARBANDINFO));
				info.cbSize	= sizeof(REBARBANDINFO);
				info.fMask	= RBBIM_CHILDSIZE;
				::SendMessage(hWndRebar,RB_GETBANDINFO,nIndex,(LPARAM)&info);
				info.cyMinChild	= sDeskBandInfo.ptMinSize.y;
				info.cyChild	= sDeskBandInfo.ptMinSize.y;
				info.cxMinChild	= sDeskBandInfo.ptMinSize.x;
				::SendMessage(hWndRebar,RB_SETBANDINFO,nIndex,(LPARAM)&info);

				//位置調整
				::SendMessage(hWndRebar,RB_GETRECT,nIndex,(LPARAM)&rect);
				::SendMessage(hWndParent,WM_SIZE,SIZE_RESTORED,MAKELPARAM(rect.Width(),rect.Height()));
			}
		}

		return	true;
	}

tabbrowser225.gif 次に「Googleツールバー」で(トップレベルHTMLとして作られている?)ドロップダウンメニューを開くとビューウインドウにきちんとフォーカスが当たらない問題を修正する。CIEUtilityのSetFocusChange内を変更する。今まではUIDeactivateを呼ぶのみだったが、InPlaceDeactivateも呼ぶようにした。
	//■処理内容追加
	//IEコントロールがフォーカスを受け取ったときbGetFocus=true、
	//IEコントロールがフォーカスを失ったときbGetFocus=falseとして呼び出す
	bool	SetFocusChange(bool bGetFocus)
	{
		if(_pIWebBrowser2 == NULL)
			return	false;

		HRESULT	hr = E_FAIL;
		CComPtr<IOleInPlaceObject> pIOleInPlaceObject;

		if(_pIWebBrowser2)
			_pIWebBrowser2->QueryInterface(&pIOleInPlaceObject);
		if(pIOleInPlaceObject == NULL)
			return	S_OK;

		if(bGetFocus)
		{
			hr = pIOleInPlaceObject->UIDeactivate();
			pIOleInPlaceObject->InPlaceDeactivate();
		}
		else
		{
			HWND hWnd;

			hr = pIOleInPlaceObject->GetWindow(&hWnd);
			if(SUCCEEDED(hr) && ::IsWindow(hWnd))
				::ShowWindow(hWnd,SW_NORMAL);
		}

		return	true;
	}

tabbrowser226.gif 同様にCIEToolbar内も変更しておく。
	//■処理内容追加
	//IInputObjectSite
	STDMETHOD(OnFocusChangeIS)(IUnknown *punkObj,BOOL fSetFocus)
	{
		HRESULT	hr = E_FAIL;
		CComPtr<IOleInPlaceObject> pIOleInPlaceObject;

		if(_pIDispatch)
			_pIDispatch->QueryInterface(&pIOleInPlaceObject);
		if(pIOleInPlaceObject == NULL)
			return	S_OK;

		if(fSetFocus)
		{
			hr = pIOleInPlaceObject->UIDeactivate();
			pIOleInPlaceObject->InPlaceDeactivate();
		}
		else
		{
			HWND hWnd;
			hr = pIOleInPlaceObject->GetWindow(&hWnd);
			if(SUCCEEDED(hr) && ::IsWindow(hWnd))
				::ShowWindow(hWnd,SW_NORMAL);
		}

		return	S_OK;
	}

tabbrowser227.gif
これでビルド/実行すると、これまで下端が切れて表示されていた「Googleツールバー」がきちんと表示されるようになった。

次回複数のInternet Explorer用ツールバーが表示できるようにするための準備をする。

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

第51回 タブがないときにGoogleツールバーが表示されないようにする (タブブラウザーを作る)

tabbrowser219.gif
これまで起動直後などタブが1つもないときには「Googleツールバー」を表示するための領域(リバー)が空白のまま表示されていた。今回はタブがない場合にはリバーが表示されないようにする。

まずGoogleツールバーの親ウインドウとして利用しているCDummyWndの処理内容を追加する。リバーの表示/非表示を切り替える関数やリバーサイズが変わったときにGoogleツールバーのウインドウサイズを変更する処理を追加した。
	//■処理内容実装
	class	CDummyWnd	: public CWindowImpl<CDummyWnd>
	{
	public:
		UINT	_nBandIndex;		//rebar上のインデックス

		CDummyWnd()
		{
			_nBandIndex = -1;
		}

		BEGIN_MSG_MAP(CDummyWnd)
			MESSAGE_HANDLER(WM_DNP_GETRBINDEX, OnDnpRbIndex)
			MESSAGE_HANDLER(WM_SIZE, OnSize)
		END_MSG_MAP()

		LRESULT OnDnpRbIndex(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
		{
			UINT*	pnIndex = (UINT*)wParam;

			if(pnIndex)
				*pnIndex = _nBandIndex;

			return	0;
		}


		LRESULT OnSize(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
		{
			bHandled = FALSE;
			if(_nBandIndex == -1)
				return	0;

			//このウインドウの直下にあるchildウインドウ=IEツールバーをrebarに全体表示する

			CRect	rect;
			HWND	hWnd;

			//rebarサイズ取得
			rect.left	= 0;
			rect.top	= 0;
			rect.right	= LOWORD(lParam);
			rect.bottom	= HIWORD(lParam);

			//子ウインドウを検索してサイズ調節
			hWnd = NULL;
			while(1)
			{
				hWnd = ::FindWindowEx(m_hWnd,hWnd,NULL,NULL);
				if(hWnd == NULL)
					break;

				::MoveWindow(hWnd,rect.left,rect.top,rect.Width(),rect.Height(),FALSE);
			}

			return	0;
		}


		bool	ShowRebar(bool bVisible)
		{
			if(_nBandIndex == -1 || IsWindow() == FALSE)
				return	false;

			::SendMessage(::GetParent(m_hWnd),RB_SHOWBAND,(WPARAM)_nBandIndex,(LPARAM)(bVisible ? TRUE : FALSE));

			return	true;
		}
	};

tabbrowser220.gif そしてOnCreate内でGoogleツールバー用のリバー生成後、そのIDをCDummyWndに渡しておく。
	LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		// コマンドバー ウィンドウの作成
		HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
		// メニューのアタッチ
		m_CmdBar.AttachMenu(GetMenu());
		// コマンドバー画像の読み込み
		m_CmdBar.LoadImages(IDR_MAINFRAME);
		// 以前のメニューの削除
		SetMenu(NULL);

		HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);

		CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
		AddSimpleReBarBand(hWndCmdBar);
		AddSimpleReBarBand(hWndToolBar, NULL, TRUE);

		_wndAddressBar.Create(m_hWnd,CRect(0,0,200,200),0,WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_CLIPCHILDREN,WS_EX_CLIENTEDGE);
		AddSimpleReBarBand(_wndAddressBar,0,TRUE);	//アドレスバーを1列で表示

		//ダミーウインドウを生成し、リバーに割り当てる。これはIEツールバーに利用
		//ここで生成してしまうと何もないリバーができてしまうが気にしない
		_wndDummy.Create(m_hWnd,CRect(0,0,500,24),0,WS_CHILD);
		AddSimpleReBarBand(_wndDummy,0,TRUE);						//1行表示

		//■追加
		//IEツールバー用のrebarのインデックス取得。_wndDummyへ割り当てると同時にrebarを非表示に
		{
			UINT	nCount;

			nCount = (UINT)::SendMessage(m_hWndToolBar,RB_GETBANDCOUNT,NULL,NULL);
			_wndDummy._nBandIndex = nCount - 1;
			_wndDummy.ShowRebar(false);			//非表示にする
		}


		CreateSimpleStatusBar();

		m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);

		UIAddToolBar(hWndToolBar);
		UISetCheck(ID_VIEW_TOOLBAR, 1);
		UISetCheck(ID_VIEW_STATUS_BAR, 1);

		// メッセージ フィルターおよび画面更新用のオブジェクト登録
		CMessageLoop* pLoop = _Module.GetMessageLoop();
		ATLASSERT(pLoop != NULL);
		pLoop->AddMessageFilter(this);
		pLoop->AddIdleHandler(this);

		CMenuHandle menuMain = m_CmdBar.GetMenu();
		m_view.SetWindowMenu(menuMain.GetSubMenu(WINDOW_MENU_POSITION));

		_cTabImageList.Create(16,16,ILC_COLOR | ILC_MASK,1,10);
		m_view.SetImageList(_cTabImageList);

		return 0;
	}

tabbrowser221.gif OnTabPageActivatedの部分でツールバーの表示/非表示が切り替わるようにする。
	//タブが選択されたときの処理
	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);	//ステータスバー解放
				}
			}

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


		bool		ret;
		CTabBrowser100View*	pView;

		pView = GetActivePageView();		//アクティブビュー取得
		if(pView == NULL)
		{
			_wndDummy.ShowRebar(false);			//■追加 リバー消去
			return	0;
		}

		_wndDummy.ShowRebar(true);			//■追加 リバー表示

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

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

		return	0;
	}

tabbrowser222.gif 今回はCDummyWndに独自メッセージを送ることでリバーのIDが取得できるようにした。そのためのメッセージを「stdafx.h」に定義しておく。
#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)
#define	WM_DNP_SHOWZONECONFIGURE	(WM_APP + 10)
#define	WM_DNP_GETRBINDEX		(WM_APP + 11)		//■追加

tabbrowser223.gif
これでタブがないときには「Googleツールバー」用のリバーが表示されなくなった。

次回はGoogleツールバーの下端が切れる問題とページ上でキー入力ができなくなるバグを修正する。

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

2009年04月10日

第50回 「スクリプト実行」「ActiveX実行」「画像表示」などをON/OFFする (タブブラウザーを作る)

tabbrowser212.gif
前回はツールバーにリンククリック時に鳴る音をON/OFFするためのボタンを追加した。今回は同じように「スクリプトの実行」「画像の表示」「AvtiveXコントロールの実行」「BGMの再生」の各項目をON/OFFするため機能を実装する。

「スクリプトの実行」や「ActiveXコントロールの実行」を今回のような手法で制御することはセキュリティ上の弱点となる。セキュリティ的に少しは弱みとならないような切り替え方法を少し考えてみたのだがどうも複雑になりそう。もともとステータスバーやアドレスバーの実装方法などセキュリティ的に最悪な部分がたくさんあるので細かいことは気にせずに単純にON/OFFを切り替えるに留める。

まずツールバーに4つのボタンを追加する。スクリプト実行のON/OFF用の「ID_SCRIPT」、画像表示用の「ID_IMAGE」、ActiveXコントロール実行用の「ID_ACTIVEX」、BGM再生用の「ID_BGM」を用意した。

tabbrowser213.gif 「MainFrm.h」で用意したボタンをツールバーのUI_ELEMENTとして登録すると同時に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_TOOL_DEVELOP, FALSE);
			UIEnable(ID_TOOL_INTERNET_OPTION, FALSE);
		}

		//ツールバーボタン。クリック音を鳴らす
		{
			bool	bDisable;

			bDisable = IsFeatureEnabled(FEATURE_DISABLE_NAVIGATION_SOUNDS);
			UISetCheck(ID_CLICK_SOUND,! bDisable);
		}

		//■追加
		//ダウンロードコントロール
		if(pView)
		{
			bool	bEnable;

			//何度もフラグを読み出してるので効率が悪いが気にしない
			bEnable = pView->IsEnableAmbientDownloadControl(DLCTL_DLIMAGES);
			UISetCheck(ID_IMAGE,bEnable);

			bEnable = pView->IsEnableAmbientDownloadControl(DLCTL_BGSOUNDS);
			UISetCheck(ID_BGM,bEnable);

			bEnable = pView->IsEnableAmbientDownloadControl(DLCTL_NO_SCRIPTS);
			UISetCheck(ID_SCRIPT,! bEnable);		//反転

			bEnable = pView->IsEnableAmbientDownloadControl(DLCTL_NO_RUNACTIVEXCTLS);
			UISetCheck(ID_ACTIVEX,! bEnable);		//反転
		}

		UIUpdateToolBar();
		return FALSE;
	}


	bool	IsFeatureEnabled(INTERNETFEATURELIST FeatureEntry)
	{
		HRESULT	hr;

		hr = ::CoInternetIsFeatureEnabled(FeatureEntry,SET_FEATURE_ON_PROCESS);
		if(hr == S_OK)
			return	true;
		return	false;
	}

	BEGIN_UPDATE_UI_MAP(CMainFrame)
		UPDATE_ELEMENT(ID_SCRIPT, UPDUI_TOOLBAR)		//■追加
		UPDATE_ELEMENT(ID_IMAGE, UPDUI_TOOLBAR)			//■追加
		UPDATE_ELEMENT(ID_ACTIVEX, UPDUI_TOOLBAR)		//■追加
		UPDATE_ELEMENT(ID_BGM, UPDUI_TOOLBAR)			//■追加
		UPDATE_ELEMENT(ID_CLICK_SOUND, UPDUI_TOOLBAR)
		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)

tabbrowser214.gif そしてツールバーが押されたときの動作を実装する。
	BEGIN_MSG_MAP(CMainFrame)
		MESSAGE_HANDLER(WM_DNP_CREATENEWTAB, OnDnpCreateNewTab)
		MESSAGE_HANDLER(WM_DNP_CHANGEFOCUS, OnDnpChangeFocus)
		MESSAGE_HANDLER(WM_DNP_CHANGEADDRESS, OnDnpChangeAddress)
		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_ID_HANDLER(ID_CLICK_SOUND, OnFileCommand)
		COMMAND_ID_HANDLER(ID_IMAGE, OnFileCommand)			//■追加
		COMMAND_ID_HANDLER(ID_BGM, OnFileCommand)			//■追加
		COMMAND_ID_HANDLER(ID_SCRIPT, OnFileCommand)		//■追加
		COMMAND_ID_HANDLER(ID_ACTIVEX, 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)
		MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
		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_IMAGE:			//画像表示
		case	ID_BGM:				//BGM再生
		case	ID_SCRIPT:			//スクリプト実行
		case	ID_ACTIVEX:			//ActiveXコントロール実行
			{
				bool	bEnable;
				long	nFlag;

				nFlag = 0;
				switch(wID)
				{
				case	ID_IMAGE:		nFlag = DLCTL_DLIMAGES;					break;
				case	ID_BGM:			nFlag = DLCTL_BGSOUNDS;					break;
				case	ID_SCRIPT:		nFlag = DLCTL_NO_SCRIPTS;				break;
				case	ID_ACTIVEX:		nFlag = DLCTL_NO_RUNACTIVEXCTLS;		break;
				}

				bEnable = pView->IsEnableAmbientDownloadControl(nFlag);
				pView->SetAmbientDownloadControl(nFlag,! bEnable);
				break;
			}

		case	ID_CLICK_SOUND:				//クリック音を再生するかどうかの設定
			{
				bool	bDisable;

				bDisable = IsFeatureEnabled(FEATURE_DISABLE_NAVIGATION_SOUNDS);
				::CoInternetSetFeatureEnabled(FEATURE_DISABLE_NAVIGATION_SOUNDS,SET_FEATURE_ON_PROCESS,bDisable ? FALSE : TRUE);
			}
			break;

		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;
	}

tabbrowser217.gif スクリプト実行のON/OFFはDISPID_AMBIENT_DLCONTROLで行われる。ここでDLCTL_DLIMAGES(画像の表示)などのフラグを設定することでON/OFFできる。
#include "mshtmdid.h"

//■追加
MIDL_INTERFACE("A419B9D4-2940-44c9-B0E0-A0B0FC61046F")
IAmbientControl : public IUnknown
{
public:
	STDMETHOD (put_nAmbient)(long newVal) = 0;
	STDMETHOD (get_nAmbient)(long* pnVal) = 0;
};

//■追加
class CAmbientControl :
	public CComObjectRootEx<CComSingleThreadModel>
	,public	IDispatchImpl<IDispatch>
	,public IOleClientSite
	,public IAmbientControl
{
	long	_nAmbient;

public:

	CAmbientControl()
	{
		_nAmbient = DLCTL_DLIMAGES | DLCTL_VIDEOS | DLCTL_BGSOUNDS;
	}

    BEGIN_COM_MAP(CAmbientControl)
        COM_INTERFACE_ENTRY(IDispatch)
        COM_INTERFACE_ENTRY(IAmbientControl)
        COM_INTERFACE_ENTRY(IOleClientSite)
    END_COM_MAP()


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

		//if(dispIdMember == DISPID_AMBIENT_USERAGENT)
		//{
		//	//pvar->vt = VT_BSTR;
		//	//pvar->bstrVal = ::SysAllocString(T2OLE(strUserAgent));
		//}

		return	E_NOTIMPL;
	}

	STDMETHOD(put_nAmbient)(long newVal)
	{
		_nAmbient = newVal;
		return	S_OK;
	}

	STDMETHOD(get_nAmbient)(long* pnVal)
	{
		if(pnVal == NULL)
			return	E_POINTER;
		*pnVal = _nAmbient;
		return	S_OK;
	}


	STDMETHOD(SaveObject)(void)
	{
		return	E_NOTIMPL;
	}

	STDMETHOD(GetMoniker)(DWORD dwAssign,DWORD dwWhichMoniker,IMoniker **ppmk)
	{
		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;
	}
};

tabbrowser215.gif
ビューウインドウ内にAmbientDownloadのフラグを取得/設定するための関数を追加する。

本来であればIWebBrowser2から直接現在のダウンロードフラグを取得するべきだが、今回は独自インターフェースIAmbientControlを実装することで、前回設定したフラグ値を取得して利用するようにした。
	CComPtr<IAmbientControl>	_pIAmbientControl;		//■追加


	//■追加
	//ダウンロードコントロール設定
	//nFlagsは DLCTL_DLIMAGES | DLCTL_VIDEOS | DLCTL_BGSOUNDS などを渡す
	bool	SetAmbientDownloadControl(long nFlags)
	{
		if(_pIAmbientControl == NULL)
			return	false;

		//設定
		_pIAmbientControl->put_nAmbient(nFlags);

		//変更の適用
		HRESULT		hr;
		CComPtr<IOleControl>	pIOleControl;

		hr = _pIWebBrowser2->QueryInterface(&pIOleControl);
		if(pIOleControl)
			hr = pIOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_DLCONTROL);

		return	SUCCEEDED(hr) ? true : false;
	}


	//■追加
	//ダウンロードコントロール取得
	//nFlagsは DLCTL_DLIMAGES | DLCTL_VIDEOS | DLCTL_BGSOUNDS などが返る
	bool	GetAmbientDownloadControl(long& nFlags)
	{
		nFlags = 0;
		if(_pIAmbientControl == NULL)
			return	false;

		return	SUCCEEDED(_pIAmbientControl->get_nAmbient(&nFlags)) ? true : false;
	}

	//■追加
	//指定したダウンロードコントロールフラグが現在有効化どうか
	//nFlagはDLCTL_DLIMAGESやDLCTL_NO_SCRIPTSなどを1つだけ渡す
	bool	IsEnableAmbientDownloadControl(long nFlag)
	{
		long	nAmbient;

		GetAmbientDownloadControl(nAmbient);

		return	(nAmbient & nFlag) ? true : false;
	}

	//■追加
	//指定したダウンロードコントロールフラグの設定/解除
	//nFlagはDLCTL_DLIMAGESやDLCTL_NO_SCRIPTSなどを1つだけ渡す
	//bEnable=trueならそのフラグを設定、falseなら解除する
	bool	SetAmbientDownloadControl(long nFlag,bool bEnable)
	{
		bool	ret;
		long	nAmbient;

		ret = GetAmbientDownloadControl(nAmbient);
		if(ret == false)
			return	false;

		if(bEnable)
			nAmbient |= nFlag;
		else
			nAmbient &= ~nFlag;

		return	SetAmbientDownloadControl(nAmbient);
	}

tabbrowser216.gif 最後にビューウインドウが生成されたときに、クライアントサイトとして登録されるようにする。
	//Create関数のオーバーライド。内部でIEの取得、接続などを行う
	HWND Create(HWND hWndParent, _U_RECT rect = NULL, LPCTSTR szWindowName = NULL,
			DWORD dwStyle = 0, DWORD dwExStyle = 0,
			_U_MENUorID MenuOrID = 0U, LPVOID lpCreateParam = NULL)
	{
		HWND	hWnd;

		hWnd = __super::Create(hWndParent,rect,szWindowName,dwStyle,dwExStyle,MenuOrID,lpCreateParam);
		if(hWnd == NULL)
			return	NULL;			//Create失敗

		QueryControl(&_pIWebBrowser2);		//_pIWebBrowser2にこのビューに関連づいているIEをセットする
		if(_pIWebBrowser2 == NULL)
			return	hWnd;			//WebBrowser取得失敗

		Advise(_pIWebBrowser2);		//IEとの接続


		//■追加
		//jacascriptや画像ダウンロードのコントロール設定
		{
			CComPtr<IOleObject>		pIOleObject;
			CComObject<CAmbientControl>*		pCAmbientControl;
			CComPtr<IAxWinAmbientDispatchEx>	pIAxWinAmbientDispatchEx;

			//ダウンロードコントロールの準備
			CComObject<CAmbientControl>::CreateInstance(&pCAmbientControl);
			if(pCAmbientControl)
				pCAmbientControl->QueryInterface(&_pIAmbientControl);

			//IEコントロールへのセット
			_pIWebBrowser2->QueryInterface(&pIOleObject);
			if(pIOleObject && pCAmbientControl)
				pIOleObject->SetClientSite(pCAmbientControl);

			//デフォルトのダウンロードコントロールを設定
			//本来ならゾーン変化をチェックしてゾーンに応じて決定すべき?
			SetAmbientDownloadControl(DLCTL_DLIMAGES | DLCTL_VIDEOS | DLCTL_BGSOUNDS);
		}

		//Googleツールバーを生成する
		{
			HRESULT	hr;
			GUID	rclsid;
			WCHAR	pszGUID[] = {L"{2318C2B1-4965-11d4-9B18-009027A5CD4F}"};		//GoogleツールバーのGUID

			::CLSIDFromString(pszGUID,&rclsid);

			_pIDeskBand = NULL;
			hr = ::CoCreateInstance(rclsid,NULL,CLSCTX_INPROC_SERVER,IID_IDeskBand,(void**)&_pIDeskBand);
			if(_pIDeskBand)
			{
				CComPtr<IObjectWithSite>	pIObjectWithSite;

				_pIDeskBand->QueryInterface(IID_IObjectWithSite,(void**)&pIObjectWithSite);

				DESKBANDINFO	sDeskBandInfo;

				//別に必要ないが情報をたくさん取得
				::ZeroMemory(&sDeskBandInfo,sizeof(DESKBANDINFO));
				sDeskBandInfo.dwMask = DBIM_MINSIZE | DBIM_MAXSIZE | DBIM_INTEGRAL | DBIM_ACTUAL | DBIM_TITLE | DBIM_MODEFLAGS | DBIM_BKCOLOR;
				hr = _pIDeskBand->GetBandInfo(0,DBIF_VIEWMODE_NORMAL,&sDeskBandInfo);

				//■■本当はきちんと調整しないとだめ!!
				CRect	rect(0,0,2000,sDeskBandInfo.ptMinSize.y);		//横サイズは十分大きいサイズを確保(//■■2000px固定)

				//デスクバンドをホスト用クラスに割り当てる
				{
					CComPtr<IIEToolbar>	pIIEToolbar;

					pIIEToolbar = new CComObject<CIEToolbar>;

					pIIEToolbar->put_hwnd(_hWndRebarIE);
					if(_pIWebBrowser2)
						pIIEToolbar->put_IWebBrowser2(_pIWebBrowser2);
					if(pIObjectWithSite)
						hr = pIObjectWithSite->SetSite(pIIEToolbar);

					if(SUCCEEDED(hr))
						hr = _pIDeskBand->ShowDW(TRUE);
				}

				//位置調整
				{
					HWND	hWnd;

					_pIDeskBand->GetWindow(&hWnd);
					if(::IsWindow(hWnd))
						::MoveWindow(hWnd,0,0,rect.Width(),rect.Height(),TRUE);
				}
			}
		}

		return	hWnd;
	}

tabbrowser218.gif
これでビルド/実行し「画像表示」をOFFにして「更新」したところ、画像が表示されなくなった。


Googleツールバー6が公開されていたのでインストールしたところ、このタブブラウザ上でGoogleツールバーの下部が少し欠けて表示されるようになってしまった。次回はこれを機会にGoogleツールバー表示部分を少し見直す。

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

2009年04月09日

第49回 Navigate時のクリック音をON/OFFする (タブブラウザーを作る)

tabbrowser207.gif
Internet ExplorerやIEコントロールでは、リンクをクリックするときなどNavigateが開始されるときにプチッというクリック音が鳴る。今回はそのクリック音を切る機能を追加する。

設定方法はいくつか考えられるが、今回はツールバーのボタンとして実装する。そのためのボタンをリソースウインドウで追加する。IDは「ID_CLICK_SOUND」とした。

tabbrowser208.gif
作成したボタンをUI_MAPに追加する。そしてOnIdleで現在音が鳴る状態なら押下状態、鳴らないならノーマルなボタン状態に設定する。

現在、クリック音が鳴るかどうかはCoInternetIsFeatureEnabledで取得できる。ただしこの関数はIE6&XPSP2以降でのみ使える関数だ。
	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_TOOL_WINDOWS_UPDATE, FALSE);
			UIEnable(ID_TOOL_DEVELOP, FALSE);
			UIEnable(ID_TOOL_INTERNET_OPTION, FALSE);
		}

		//■追加
		//ツールバーボタン。クリック音を鳴らす
		{
			bool	bDisable;

			bDisable = IsFeatureEnabled(FEATURE_DISABLE_NAVIGATION_SOUNDS);
			UISetCheck(ID_CLICK_SOUND,! bDisable);
		}

		UIUpdateToolBar();
		return FALSE;
	}


	//■追加
	bool	IsFeatureEnabled(INTERNETFEATURELIST FeatureEntry)
	{
		HRESULT	hr;

		hr = ::CoInternetIsFeatureEnabled(FeatureEntry,SET_FEATURE_ON_PROCESS);
		if(hr == S_OK)
			return	true;
		return	false;
	}

	BEGIN_UPDATE_UI_MAP(CMainFrame)
		UPDATE_ELEMENT(ID_CLICK_SOUND, UPDUI_TOOLBAR)		//■追加
		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)

tabbrowser209.gif
さらにツールバーのボタンがクリックされたときの処理を追加する。

クリック音が鳴らないようにする関数はCoInternetSetFeatureEnabledで、これもXP SP2&IE6以降でのみ使えるAPIとなる。
	BEGIN_MSG_MAP(CMainFrame)
		MESSAGE_HANDLER(WM_DNP_CREATENEWTAB, OnDnpCreateNewTab)
		MESSAGE_HANDLER(WM_DNP_CHANGEFOCUS, OnDnpChangeFocus)
		MESSAGE_HANDLER(WM_DNP_CHANGEADDRESS, OnDnpChangeAddress)
		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_ID_HANDLER(ID_CLICK_SOUND, 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)
		MESSAGE_HANDLER(WM_MENUSELECT, OnMenuSelect)
		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_CLICK_SOUND:				//クリック音を再生するかどうかの設定
			{
				bool	bDisable;

				bDisable = IsFeatureEnabled(FEATURE_DISABLE_NAVIGATION_SOUNDS);
				::CoInternetSetFeatureEnabled(FEATURE_DISABLE_NAVIGATION_SOUNDS,SET_FEATURE_ON_PROCESS,bDisable ? FALSE : TRUE);
			}
			break;

		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;
	}

tabbrowser210.gif ついにで今までアドレスバーが一列で表示されず、ツールバーの一部が隠れてしまっていたので、アドレスバーが一列で表示されるように修正する。
	LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		// コマンドバー ウィンドウの作成
		HWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault, NULL, ATL_SIMPLE_CMDBAR_PANE_STYLE);
		// メニューのアタッチ
		m_CmdBar.AttachMenu(GetMenu());
		// コマンドバー画像の読み込み
		m_CmdBar.LoadImages(IDR_MAINFRAME);
		// 以前のメニューの削除
		SetMenu(NULL);

		HWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd, IDR_MAINFRAME, FALSE, ATL_SIMPLE_TOOLBAR_PANE_STYLE);

		CreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);
		AddSimpleReBarBand(hWndCmdBar);
		AddSimpleReBarBand(hWndToolBar, NULL, TRUE);

		_wndAddressBar.Create(m_hWnd,CRect(0,0,200,200),0,WS_CHILD | WS_VISIBLE | CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_CLIPCHILDREN,WS_EX_CLIENTEDGE);
		AddSimpleReBarBand(_wndAddressBar,0,TRUE);	//■変更 アドレスバーを1列で表示

		//ダミーウインドウを生成し、リバーに割り当てる。これはIEツールバーに利用
		//ここで生成してしまうと何もないリバーができてしまうが気にしない
		_wndDummy.Create(m_hWnd,CRect(0,0,500,24),0,WS_CHILD);
		AddSimpleReBarBand(_wndDummy,0,TRUE);						//1行表示

		CreateSimpleStatusBar();

		m_hWndClient = m_view.Create(m_hWnd, rcDefault, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, WS_EX_CLIENTEDGE);

		UIAddToolBar(hWndToolBar);
		UISetCheck(ID_VIEW_TOOLBAR, 1);
		UISetCheck(ID_VIEW_STATUS_BAR, 1);

		// メッセージ フィルターおよび画面更新用のオブジェクト登録
		CMessageLoop* pLoop = _Module.GetMessageLoop();
		ATLASSERT(pLoop != NULL);
		pLoop->AddMessageFilter(this);
		pLoop->AddIdleHandler(this);

		CMenuHandle menuMain = m_CmdBar.GetMenu();
		m_view.SetWindowMenu(menuMain.GetSubMenu(WINDOW_MENU_POSITION));

		_cTabImageList.Create(16,16,ILC_COLOR | ILC_MASK,1,10);
		m_view.SetImageList(_cTabImageList);

		return 0;
	}

tabbrowser211.gif
これでツールバーにプッシュ式のボタンが追加され、押し込んだ状態のときはクリック音が鳴り、そうでないときはクリック音が鳴らなくなった。

次回からはスクリプトや画像表示のON/OFF用のボタンを用意し、今回のクリック音のように自由に設定できるようにする。

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

第48回 ゾーン設定ウインドウを開く (タブブラウザーを作る)

tabbrowser202.gif
前回までにステータスバーに現在開いているページのゾーン名やゾーンのアイコンを表示した。今回はその部分をダブルクリックしたときにゾーン設定画面が開くようにする。

処理の流れはステータスバーのダブルクリックからプライバシーレポートを表示したときと同じようになる。まず「stdafx.h」内にステータスバーからビューウインドウへダブルクリックされたときに送るための独自メッセージを追加する。
#define	WM_DNP_SHOWZONECONFIGURE	(WM_APP + 10)		//■追加

tabbrowser203.gif そしてステータスバーがダブルクリックされたときにビューウインドウへメッセージを送信する。
	//ステータスバーのダブルクリック処理
	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(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_ZONE:
					::SendMessage(_hWndNotify,WM_DNP_SHOWZONECONFIGURE,NULL,NULL);
					break;

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

				break;
			}

			i++;
		}

		return	0;
	}

tabbrowser204.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)
		MESSAGE_HANDLER(WM_DNP_SHOWZONECONFIGURE, OnShowZoneConfigure)		//■追加
	END_MSG_MAP()


private:


	LRESULT OnShowZoneConfigure(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
	{
		ShowZoneConfigure(m_hWnd);
		return	0;
	}

tabbrowser205.gif 最後に実際にゾーン設定画面を開く処理を実装する。ゾーン設定画面はshlwapi.dllからnoname@383でエクスポートされているZoneConfigureWという関数により開く。
	//■追加
	//ゾーン設定の表示
	bool	ShowZoneConfigure(HWND hWnd,LPCTSTR pszURL)
	{
		HMODULE	hDLL;
		void (WINAPI* pfnZoneConfigureW)(HWND,LPCWSTR) = NULL;

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

		(FARPROC&)pfnZoneConfigureW = ::GetProcAddress(hDLL,(LPCSTR)383);
		if(pfnZoneConfigureW)
			(*pfnZoneConfigureW)(NULL,(CAtlStringW)pszURL);

		::FreeLibrary(hDLL);

		return	pfnZoneConfigureW ? true : false;
	}

	//■追加
	//ゾーン設定の表示
	bool	ShowZoneConfigure(HWND hWnd)
	{
		HRESULT		hr;
		CComBSTR	bstrURL;

		if(_pIWebBrowser2 == NULL)
			return	false;

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

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

tabbrowser206.gif
これでビルド/実行してステータスバーのゾーン情報の部分をダブルクリックするとゾーン設定画面が開いた。

次回はリンクをクリックしたときに鳴るクリック音を消す設定をする。

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

第47回 現在のゾーンのアイコンを表示する (タブブラウザーを作る)

tabbrowser198.gif
前回はステータスバーへ現在のインターネットゾーン名を表示した。今回はゾーン用のアイコンを表示する。

ありがたいことにゾーン名を取得するときに利用したIInternetZoneManager::GetZoneAttributesはゾーン名に加えて、表示用のアイコンファイル名も教えてくれる。今回はこの情報を元にアイコンを表示する。

まずはファイルからアイコンを読み込むようにCIconManagerに機能を実装する。ステータスバーにアイコンを表示するたびにファイルからアイコンをロードしていたのでは効率が悪いので、_acItemという配列を用意してそこに一度読み込んだアイコンファイルの情報を格納しておくことにした。
//アイコンを管理
//アイコンをAddする関数などは未実装。今後追加
class	CIconManager
{
protected:
	CAtlArray<HICON>	_ahIcon;		//アイコンリスト

	//■追加
	//ファイルからアイコンを読み込むときのキャッシュ用クラス
	class	CItem
	{
	public:
		CItem()
		{
			nIconIndex = -1;
		}

		CItem(LPCTSTR pszFile,UINT nIndex)
		{
			strIconFile = pszFile;
			nIconIndex = nIndex;
		}

		CAtlString	strIconFile;
		UINT		nIconIndex;
	};

	CAtlArray<CItem>	_acItem;	//■追加 ファイルから読み込んだアイコンキャッシュ情報

	//■追加
	//キャッシュ情報からアイコンを取得する
	bool	GetIcon(LPCTSTR pszFile,HICON& hIcon)
	{
		size_t	i;
		size_t	nSize;

		nSize = _acItem.GetCount();
		for(i = 0; i < nSize; i++)
		{
			if(_acItem[i].strIconFile != pszFile)
				continue;

			hIcon = GetIcon(_acItem[i].nIconIndex);
			return	true;
		}

		hIcon = NULL;
		return	false;
	}

	//■追加
	//キャッシュおよび_ahIconへアイコンを追加する
	//ファイルから読み込んだ場合は必ずこの関数で追加すること
	bool	AddIcon(LPCTSTR pszFile,HICON hIcon)
	{
		UINT	nIndex;

		nIndex = _ahIcon.Add(hIcon);
		_acItem.Add(CItem(pszFile,nIndex));

		return	true;
	}

tabbrowser199.gif そしてファイルから実際にアイコンを読み込む処理を実装する。IInternetZoneManager::GetZoneAttributesが教えてくれるアイコンファイルは「xxx.dll#12345」のようにファイル名+リソース名という形で取得できる。そのままでは処理できないので一度「#」で分割して読み込む。
	//■追加
	//ファイルやファイルのリソースからアイコンを取得
	HICON	GetIcon(LPCTSTR pszIconFile)
	{
		bool		ret;
		int			nFind;
		HICON		hIcon;

		ret = GetIcon(pszIconFile,hIcon);
		if(ret)
			return	hIcon;

		//LoadIconのは自動でDestroyされる
		hIcon = (HICON)::LoadImage(NULL,pszIconFile,IMAGE_ICON,0,0,LR_LOADFROMFILE | LR_DEFAULTCOLOR | LR_DEFAULTSIZE);
		if(hIcon)
			hIcon = (HICON)::CopyImage(hIcon,IMAGE_ICON,::GetSystemMetrics(SM_CXSMICON),::GetSystemMetrics(SM_CYSMICON),LR_COPYFROMRESOURCE | LR_COPYDELETEORG | LR_COPYRETURNORG);
		if(hIcon)
		{
			AddIcon(pszIconFile,hIcon);
			return	hIcon;
		}

		//アイコンがロードできなかった場合は...
		//「c:¥xxx.dll#0010」のようなリソース指定としてトライ

		HMODULE		hDLL;
		CAtlString	strFile(pszIconFile);

		nFind = strFile.ReverseFind(_T('#'));
		if(nFind < 0)
			return	NULL;		//リソース名ではなかった

		hDLL = ::LoadLibrary(strFile.Left(nFind));
		if(hDLL == NULL)
			return	NULL;

		//LoadIconのは自動でDestroyされる
		hIcon = (HICON)::LoadImage(hDLL,(LPCTSTR)::_tcstoi64(strFile.Right(strFile.GetLength() - nFind - 1),NULL,10),IMAGE_ICON,0,0,LR_DEFAULTCOLOR | LR_DEFAULTSIZE);
		if(hIcon)
			hIcon = (HICON)::CopyImage(hIcon,IMAGE_ICON,::GetSystemMetrics(SM_CXSMICON),::GetSystemMetrics(SM_CYSMICON),LR_COPYFROMRESOURCE | LR_COPYDELETEORG | LR_COPYRETURNORG);

		::FreeLibrary(hDLL);

		AddIcon(pszIconFile,hIcon);		//NULLでも登録してしまう

		return	hIcon;
	}

tabbrowser200.gif そして最後にステータスバークラスの中でゾーン用のアイコンを表示する処理を追加する。
	bool	SetZone(DWORD dwZone)
	{
		_dwZone = dwZone;

		if(IsWindow() == FALSE)
			return	true;			//trueを返す

		//ゾーンのテキストをステータスバーに表示
		{
			ZONEATTRIBUTES	sZoneAttributes;
			CComPtr<IInternetZoneManager>	pIInternetZoneManager;

			::ZeroMemory(&sZoneAttributes,sizeof(ZONEATTRIBUTES));
			sZoneAttributes.cbSize = sizeof(ZONEATTRIBUTES);

			pIInternetZoneManager.CoCreateInstance(CLSID_InternetZoneManager,NULL,CLSCTX_INPROC_SERVER);
			if(pIInternetZoneManager)
				pIInternetZoneManager->GetZoneAttributes(dwZone,&sZoneAttributes);

			CAtlString		strZone = sZoneAttributes.szDisplayName;
			CStatusBarCtrl	wndStatusBar = m_hWnd;

			//■追加
			//ゾーンアイコン表示
			{
				HICON	hIcon = NULL;

				if(sZoneAttributes.szIconPath && *sZoneAttributes.szIconPath)
					hIcon = _cIconList.GetIcon(sZoneAttributes.szIconPath);
				wndStatusBar.SetIcon(PAIN_ZONE,hIcon);
			}

			wndStatusBar.SetText(PAIN_ZONE,strZone);
		}

		return	true;
	}

tabbrowser201.gif
これでビルド/実行するとステータスバーにゾーンのアイコンが表示されるようになった。ステータスバーの幅が狭すぎてゾーン名がはみ出てしまったのはご愛敬。そのうちに修正することにして今は保留しておく。

次回はステータスバーのゾーン情報表示部分をダブルクリックしたときにゾーン設定画面が開くようにする。

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

第46回 現在のゾーン情報を表示する (タブブラウザーを作る)

tabbrowser193.gif
今回はステータスバーにアクセスしているURLに応じて「インターネット」や「コンピュータ」「信頼済みサイト」などのインターネットゾーン表示をする。

今回のゾーン情報の取得はInternet Explorer 6 SP2以降のCOMインターフェースを利用する。そのためまずは「stdafx.h」でIE6 SP2以降を示す0x603を_WIN32_IEの値として定義する。
#define WINVER			0x0500
#define _WIN32_WINNT	0x0501
#define _WIN32_IE		0x0603		//■変更 IE6SP2以降
#define _RICHEDIT_VER	0x0200

tabbrowser194.gif そしてビュークラス内に実際のゾーン取得処理を実装する。IInternetSecurityManagerをCoCreateし、URLを渡すことでゾーン値を取得、それをステータスバーへセットする。
	//■追加
	//ゾーンの取得
	bool	GetZone(LPCTSTR pszURL,DWORD& dwZone)
	{
		HRESULT		hr;
		CAtlStringW	ustrURL(pszURL);
		CComPtr<IInternetSecurityManager>	pIInternetSecurityManager;

		dwZone = URLZONE_INVALID;
		pIInternetSecurityManager.CoCreateInstance(CLSID_InternetSecurityManager,NULL,CLSCTX_INPROC_SERVER);
		if(pIInternetSecurityManager == NULL)
			return	false;

		hr = pIInternetSecurityManager->MapUrlToZone(ustrURL,&dwZone,0);

		return	SUCCEEDED(hr) ? true : false;
	}


	//メインウインドウへアドレス変更を通知する
	bool	NotifyChangeURL(LPCTSTR pszURL)
	{
		//■追加
		//インターネットゾーンの取得
		{
			DWORD	dwZone;

			GetZone(pszURL,dwZone);
			_wndStatusbar.SetZone(dwZone);		//ステータスバーへ設定
		}

		if(_pTabView == NULL)
			return	false;
		if(_pTabView->GetActivePage() != _pTabView->PageIndexFromHwnd(m_hWnd))
			return	false;			//このビューがアクティブでなければ処理しない

		GetTopLevelWindow().SendMessage(WM_DNP_CHANGEADDRESS,(WPARAM)pszURL);

		return	true;
	}

tabbrowser195.gif ステータスバー側で受け取った値を保持しておくための変数を用意しておく。
class	CIELikeStatusbar	: public CWindowImpl<CIELikeStatusbar>
{
	CIconManager	_cIconList;

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


	CAtlString	_strText;

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

	bool	_bPageError;	//現在のページでスクリプトエラーなどがあればtrue、通常はfalse
	bool	_bPrivate;		//現在のページがプライバシーインパクト状態ならtrue、通常はfalse
	bool	_bSecure;		//現在のページがセキュアならtrue、通常はfalse
	DWORD	_dwZone;		//■追加 現在のページのゾーン

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

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

tabbrowser196.gif そしてビューウインドウ側から受け取ったゾーン値を保存しておくと同時に、DWORD値から表示用の文字列へ変換してステータスバーへ表示する。
	//ステータスバー表示更新
	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);
		}

		//ステータスバーのアイコン変更
		{
			SetPageError(_bPageError);
			SetPrivacy(_bPrivate);
			SetSecure(_bSecure);
		}

		//■追加
		//ゾーン設定
		{
			SetZone(_dwZone);
		}

		return	true;
	}


	//■追加
	bool	SetZone(DWORD dwZone)
	{
		_dwZone = dwZone;

		if(IsWindow() == FALSE)
			return	true;			//trueを返す

		//ゾーンのテキストをステータスバーに表示
		{
			ZONEATTRIBUTES	sZoneAttributes;
			CComPtr<IInternetZoneManager>	pIInternetZoneManager;

			::ZeroMemory(&sZoneAttributes,sizeof(ZONEATTRIBUTES));
			sZoneAttributes.cbSize = sizeof(ZONEATTRIBUTES);

			pIInternetZoneManager.CoCreateInstance(CLSID_InternetZoneManager,NULL,CLSCTX_INPROC_SERVER);
			if(pIInternetZoneManager)
				pIInternetZoneManager->GetZoneAttributes(dwZone,&sZoneAttributes);

			CAtlString		strZone = sZoneAttributes.szDisplayName;
			CStatusBarCtrl	wndStatusBar = m_hWnd;

			wndStatusBar.SetText(PAIN_ZONE,strZone);
		}

		return	true;
	}

tabbrowser197.gif
これでビルド/実行するとステータスバーに開いているページのゾーン名が表示されるようになった。

次回はゾーン名に加えてゾーン用のアイコンを表示する。

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

第45回 セキュリティやプライバシーアイコンを表示する (タブブラウザーを作る)

tabbrowser184.gif
ここ数回の実装でステータスバーをダブルクリックすることでプライバシーレポートとセキュリティレポートを表示できるようになった。

今回はステータスバーにこれらの状態を示すアイコンを表示する。まずは表示するためのアイコンを作る。リソースウインドウの「Icon」で右クリックして現われるメニューから「Iconを挿入」を選択する。


実際にInternet Explorerで利用しているアイコンをプログラム内からロードして使うようにしてもいい。しかしInternet Explorer 6と7/8では格納されている場所も形式も変更されたためちょっと実装が面倒なので今回は自分で作ることにした。

tabbrowser185.gif
今回はステータスバーへ表示するアイコンを作るため、32x32サイズは不要となる。そのため32x32の上で右クリックをして現われるメニューから「イメージタイプの削除」を選択して消してしまう。

tabbrowser186.gif
そしてアイコンを作成する。まずはプライバシーインパクト状態のアイコンを作った。IDは「IDI_PRIVACY」とした。

tabbrowser187.gif
同様の手順で「IDI_SECURITY」というセキュア状態用のアイコンも作っておく。

tabbrowser188.gif そしてCIconManager内で作成した2つのアイコンがロードされるようにする。
	enum	ICON_INDEX
	{
		ICON_WARNING_SM = 0,			//警告アイコン。スクリプトエラー時に利用
		ICON_SECURITY_SM,				//■追加 鍵のアイコン。セキュリティロック時利用
		ICON_PRIVACY_SM,				//■追加 プライバシーのアイコン。クッキー存在時などに利用
	};

	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);

		//■追加
		{
			//鍵のアイコン
			//LoadIconのは自動でDestroyされる
			hIcon = ::LoadIcon(::_Module.m_hInst,MAKEINTRESOURCE(IDI_SECURITY));
			hIcon = (HICON)::CopyImage(hIcon,IMAGE_ICON,::GetSystemMetrics(SM_CXSMICON),::GetSystemMetrics(SM_CYSMICON),LR_COPYFROMRESOURCE | LR_COPYDELETEORG | LR_COPYRETURNORG);
			nIndex = _ahIcon.Add(hIcon);
			ATLASSERT(nIndex == ICON_SECURITY_SM);
		}

		//■追加
		{
			//プライバシーのアイコン
			//LoadIconのは自動でDestroyされる
			hIcon = ::LoadIcon(::_Module.m_hInst,MAKEINTRESOURCE(IDI_PRIVACY));
			hIcon = (HICON)::CopyImage(hIcon,IMAGE_ICON,::GetSystemMetrics(SM_CXSMICON),::GetSystemMetrics(SM_CYSMICON),LR_COPYFROMRESOURCE | LR_COPYDELETEORG | LR_COPYRETURNORG);
			nIndex = _ahIcon.Add(hIcon);
			ATLASSERT(nIndex == ICON_PRIVACY_SM);
		}

		return	true;
	}

tabbrowser189.gif 次にCIELikeStatusbarに現在のページの状態を保存するための変数を追加する。この付近の流れはスクリプトエラーが発生したときのアイコン表示とまったく同じ処理になる。
	bool	_bPageError;	//現在のページでスクリプトエラーなどがあればtrue、通常はfalse
	bool	_bPrivate;		//■追加 現在のページがプライバシーインパクト状態ならtrue、通常はfalse
	bool	_bSecure;		//■追加 現在のページがセキュアならtrue、通常はfalse

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

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

tabbrowser190.gif CIELikeStatusbarに実際にページ状態に応じてアイコンを表示する処理をおく。
	//ステータスバー表示更新
	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);
		}

		//■処理変更
		//ステータスバーのアイコン変更
		{
			SetPageError(_bPageError);
			SetPrivacy(_bPrivate);
			SetSecure(_bSecure);
		}

		return	true;
	}

	//■追加
	//アイコンをステータスバーに設定/消去
	//nPainは表示するペイン
	//nIconIndexはCIconManager上でのインデックス
	//bSet=trueならアイコン設定。bSet=falseならnIconIndexを無視してアイコンを消去
	bool	SetIcon(int nPain,UINT nIconIndex,bool bSet)
	{
		if(IsWindow() == FALSE)
			return	false;

		BOOL	ret;
		CStatusBarCtrl	wndStatusBar = m_hWnd;

		if(bSet)
			ret = wndStatusBar.SetIcon(nPain,_cIconList.GetIcon(nIconIndex));
		else
			ret = wndStatusBar.SetIcon(nPain,NULL);

		return	ret ? true : false;
	}

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

		//■処理変更
		return	SetIcon(PAIN_DEFAULT,CIconManager::ICON_WARNING_SM,_bPageError);
	}

	//■追加
	bool	SetPrivacy(bool bPrivate)
	{
		_bPrivate = bPrivate;			//状態保持

		return	SetIcon(PAIN_PRIVACY_REPORT,CIconManager::ICON_PRIVACY_SM,_bPrivate);
	}

	//■追加
	bool	SetSecure(bool bSecure)
	{
		_bSecure = bSecure;			//状態保持

		return	SetIcon(PAIN_SECURITY_REPORT,CIconManager::ICON_SECURITY_SM,_bSecure);
	}

tabbrowser191.gif
最後にビューウインドウからステータスバー側にページの状態が伝わるようにする。

プライバシー状態やセキュリティ状態はIEコントロールからそれぞれDISPID_PRIVACYIMPACTEDSTATECHANGE、DISPID_SETSECURELOCKICONで届く。しかしどちらもMSDNライブラリの説明は間違えているようなので注意が必要だ。
	//■処理内容実装
	//MSDNにはVT_BOOLとあるが、BOOLとの間違え
	void __stdcall OnPrivacyImpactedStateChange(BOOL bPrivacyImpacted)
	{
		if(bPrivacyImpacted == FALSE)
			_wndStatusbar.SetPrivacy(false);
		else
			_wndStatusbar.SetPrivacy(true);
	}

	//■処理内容実装
	//MSDNにはVARIANTとあるが、longとの間違え
	void __stdcall OnSetSecureLockIcon(long lSecureLockIcon)
	{
		//本当ならlSecureLockIconは種類がいっぱいあるが、とりあえずセキュアかそうでないかのみで処理

		if(lSecureLockIcon == secureLockIconUnsecure)
			_wndStatusbar.SetSecure(false);
		else
			_wndStatusbar.SetSecure(true);
	}

tabbrowser192.gif
これでビルド/実行するとステータスバーにSSL通信時は鍵、クッキーなどを利用したべージでは変な目のアイコンが表示されるようになった。

次回は「信頼済みサイト」や「インターネット」などのゾーン情報を取得してステータスバーに表示する。

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

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