第55回 インストールされているすべてのIEツールバーを表示する (タブブラウザーを作る)

tabbrowser245.gif
前回までの作業で「Googleツールバー」を複数表示できるようになった。今回は「Googleツールバー」だけでなく、ほかのInternet Explorer用ツールバーも表示できるようにする。

まず、現在Internet Explorer用として登録されている利用可能なツールバー情報を保存しておくためのクラスを用意する。
	//■追加
	class	CAvailableIEToolbar
	{
	public:
		CAtlString	strName;
		IID			clsidToolbar;

		CAvailableIEToolbar()
		{
			clsidToolbar = GUID_NULL;
		}

		CAvailableIEToolbar(const IID& clsid,LPCTSTR pszName)
		{
			clsidToolbar = clsid;
			strName = pszName;
		}
	};

	CAtlArray<CAvailableIEToolbar>	_acAvailableIEToolbar;	//■追加



	//■追加
	//指定したHKEY内のレジストリキー名を列挙
	bool	RegEnumKeyName(HKEY hKey,CAtlArray<CAtlString>& astrClsid)
	{
		int		i;
		LONG	nRet;

		i = 0;
		while(1)
		{
			TCHAR	pszName[2048];
			DWORD	dwLen;
			DWORD	dwType;

			//レジストリ内を列挙
			dwLen = 2048;
			*pszName = NULL;
			nRet = ::RegEnumValue(hKey,i++,pszName,&dwLen,NULL,&dwType,NULL,NULL);
			if(nRet != ERROR_SUCCESS)
				break;
			if(pszName == NULL || *pszName == NULL)
				continue;

			astrClsid.Add(pszName);
		}

		return	true;
	}

tabbrowser246.gif レジストリから利用可能なIE用ツールバーのCLSIDを取得する。HKEY_CURRENT_USERとHKEY_LOCAL_MACHINEの2箇所に保存されているため、それら両方を読み込み重複チェックをしてから保存しておく。
	//■追加
	//レジストリに登録されているIEツールバーを見つけ
	//_acAvailableIEToolbarに格納する
	bool	EnumAvailableIEToolbar(void)
	{
		LONG		nRet;
		CRegKey		cRegistry;
		CAtlArray<CAtlString>	astrClsid;

		_acAvailableIEToolbar.RemoveAll();

		//最初にレジストリからIEツールバーかもしれないレジストリキーをすべて列挙して
		//astrClsidへ格納

		//ユーザー専用のIEツールバーかもしれないレジストリキーを列挙
		nRet = cRegistry.Open(HKEY_CURRENT_USER,_T("Software\\Microsoft\\Internet Explorer\\Toolbar\\WebBrowser"));
		if(nRet == ERROR_SUCCESS)
		{
			RegEnumKeyName(cRegistry.m_hKey,astrClsid);
			cRegistry.Close();
		}

		//ユーザー共通のIEツールバーかもしれないレジストリキーを列挙
		nRet = cRegistry.Open(HKEY_LOCAL_MACHINE,_T("Software\\Microsoft\\Internet Explorer\\Toolbar"));
		if(nRet == ERROR_SUCCESS)
		{
			bool	bFind;
			size_t	i;
			size_t	j;
			size_t	nSize;
			CAtlArray<CAtlString>	astrClsid2;

			RegEnumKeyName(cRegistry.m_hKey,astrClsid2);
			cRegistry.Close();

			//重複チェックして重複していないものだけastrClsid2からastrClsidへコピー
			nSize = astrClsid.GetCount();
			for(i = 0; i < astrClsid2.GetCount(); i++)
			{
				bFind = false;
				for(j = 0; j < nSize; j++)
				{
					if(astrClsid[j].CompareNoCase(astrClsid2[i]))
						continue;

					bFind = true;		//重複が見つかった
					break;
				}

				if(bFind)
					continue;

				//重複はなかった
				astrClsid.Add(astrClsid2[i]);
			}
		}


		//astrClsidに格納されているIEツールバーかもしれないレジストリキーが
		//IEツールバーかどうかをチェックして_acAvailableIEToolbarへ追加

		size_t	i;
		size_t	nSize;

		nSize = astrClsid.GetCount();
		for(i = 0; i < nSize; i++)
		{
			HRESULT	hr;
			GUID	rclsid;
			CAtlStringW	ustrName;
			CAtlString	strName;

			CComPtr<IDeskBand>	pIDeskBand;

			//文字列からIIDへ変換
			ustrName = astrClsid[i];
			hr = ::CLSIDFromString(ustrName.GetBuffer(0),&rclsid);
			if(FAILED(hr))
				continue;

			//ためしにCoCreateしてIDeskBandかをチェック
			hr = ::CoCreateInstance(rclsid,NULL,CLSCTX_INPROC_SERVER,IID_IDeskBand,(void**)&pIDeskBand);
			if(pIDeskBand == NULL)
				continue;
			pIDeskBand = NULL;

			/////////////////////////
			//IEツールバーが見つかった

			CLSIDtoUIString(rclsid,strName);
			_acAvailableIEToolbar.Add(CAvailableIEToolbar(rclsid,strName));
		}

		return	true;
	}

tabbrowser244.gif GUIDなCLSIDだけでは不便なので、CLSIDから「Google Toolbar」や「MSN Toolbar」というような表示用文字列を取得する。今回はレジストリを参照し、CLSIDとPROGIDの2つのみをチェックするようにした。
	//■追加
	//CLSIDをUI用の文字列に変換する
	bool	CLSIDtoUIString(const IID& rclsid,CAtlString& strText)
	{
		HRESULT		hr;
		LONG		nRet;
		ULONG		nChars;
		TCHAR		pszName[2048];
		WCHAR*		pwszString;
		CRegKey		cReg2;
		CAtlString	strKey;

		strText = _T("");

		/////////////////////////////////////
		// HKEY_CLASSES_ROOT\\CLSID\\{xxxxxxxx}
		//からUI名の取得を試みる
		//

		pwszString = NULL;
		hr = ::StringFromCLSID(rclsid,&pwszString);
		if(FAILED(hr))
			return	false;

		strKey = _T("CLSID\\") + (CAtlString)pwszString;
		::CoTaskMemFree(pwszString);

		nRet = cReg2.Open(HKEY_CLASSES_ROOT,strKey);
		if(nRet == ERROR_SUCCESS)
		{
			nChars = 2048;
			nRet = cReg2.QueryStringValue(NULL,pszName,&nChars);
			cReg2.Close();
			if(nRet == ERROR_SUCCESS)
			{
				strText = pszName;
				if(strText != _T(""))
					return	true;
			}
		}


		/////////////////////////////////////
		// HKEY_CLASSES_ROOT\\xxxx.xxxx.xxxx
		//(プログラムID)からUI名の取得を試みる
		//

		pwszString = NULL;
		hr = ::ProgIDFromCLSID(rclsid,&pwszString);
		strKey = pwszString;
		::CoTaskMemFree(pwszString);

		nRet = cReg2.Open(HKEY_CLASSES_ROOT,strKey);
		if(nRet == ERROR_SUCCESS)
		{
			nChars = 2048;
			nRet = cReg2.QueryStringValue(NULL,pszName,&nChars);
			cReg2.Close();
			if(nRet == ERROR_SUCCESS)
			{
				strText = pszName;
				if(strText != _T(""))
					return	true;
			}
		}

		strText = strKey;

		return	false;
	}

tabbrowser247.gif 最後にOnCreate内で利用可能なIE用ツールバーを探しだして、そのすべてを表示するようにした。
	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列で表示

		//■変更
		{
			size_t	i;
			size_t	nSize;

			EnumAvailableIEToolbar();

			nSize = _acAvailableIEToolbar.GetCount();
			for(i = 0; i < nSize; i++)
			{
				AddIEToolbar(_acAvailableIEToolbar[i].clsidToolbar);
			}
		}


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

tabbrowser248.gif
これで実行すると、インストールされているIE用ツールバーの分だけリバーが作られ、複数のIE用ツールバーが表示されるようになった。

一番上の「DinopSearchBar」は内部処理がIEに直接アクセスする形で実装されているためきちんと表示されず、2つ目の「Adobe PDF」はリバーサイズがきちんと設定されず、4番目の「Gooスティック」はウインドウサイズ変更時の再描画処理がきちんとされていないなど、まだきちんと動かない部分も多いが、とりあえずはいろいろなIE用のツールバーが利用可能になった。

次回はメニューからIE用ツールバーを選択して表示できるようにする。

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


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