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

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

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


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