IE 工具列頻帶 (DeskBand) 是在 IE 進程內載入的 COM 物件,需實作三大介面:
SetSite(IUnknown*) 傳遞站點指標,物件可 QueryInterface 取得 IWebBrowser2 等服務。IDockingWindow → IOleWindow):提供頻帶尺寸、標題、模式資訊 (GetBandInfo)。UIActivateIO, HasFocusIO, TranslateAcceleratorIO)。Support IObjectWithSite、Support IDeskBand、Support IInputObject (或手動加入介面)。CComObjectRootEx → IObjectWithSiteImpl → IDeskBandImpl → IInputObjectImpl → CComCoClass。
STDMETHOD(SetSite)(IUnknown* pUnkSite)
{
if (m_spSite) m_spSite->SetSite(NULL); // 釋放舊站點
m_spSite = pUnkSite;
if (pUnkSite)
{
// 取得 IE 視窗句柄建立工具列子視窗
HWND hParent;
pUnkSite->QueryInterface(IID_IWebBrowser2, (void**)&m_spBrowser);
m_spBrowser->get_HWND((LONG_PTR*)&hParent);
// 建立工具列視窗 (WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN)
m_hWnd = CreateWindowEx(0, _T("ToolbarWindow32"), NULL,
WS_CHILD | WS_VISIBLE | CCS_TOP | TBSTYLE_FLAT,
0, 0, 200, 24, hParent, NULL, _Module.GetResourceInstance(), NULL);
// 初始化按鈕、下拉選單等...
}
return S_OK;
}
STDMETHOD(GetBandInfo)(DWORD dwBandID, DWORD dwViewMode, DESKBANDINFO* pdbi)
{
if (pdbi->dwMask & DBIM_MINSIZE)
pdbi->ptMinSize = { 120, 24 };
if (pdbi->dwMask & DBIM_MAXSIZE)
pdbi->ptMaxSize = { -1, 24 }; // 寬度可變
if (pdbi->dwMask & DBIM_INTEGRAL)
pdbi->ptIntegral = { 1, 1 };
if (pdbi->dwMask & DBIM_ACTUAL)
pdbi->ptActual = { 200, 24 };
if (pdbi->dwMask & DBIM_TITLE)
wcscpy(pdbi->wszTitle, L"我的工具列");
if (pdbi->dwMask & DBIM_MODEFLAGS)
pdbi->dwModeFlags = DBIMF_VARIABLEHEIGHT | DBIMF_SUNKEN;
return S_OK;
}
STDMETHOD(UIActivateIO)(BOOL fActivate, LPMSG lpMsg)
{
if (fActivate) ::SetFocus(m_hWndEdit); // 激活時聚焦編輯框
return S_OK;
}
STDMETHOD(HasFocusIO)() { return (::GetFocus() == m_hWndEdit) ? S_OK : S_FALSE; }
STDMETHOD(TranslateAcceleratorIO)(LPMSG lpMsg)
{
// 處理 Ctrl+Enter 等加速鍵
return S_FALSE;
}
編譯產生 DLL 後,regsvr32 MyBand.dll 註冊。IE → 檢視 → 工具列 → 勾選「我的工具列」即可載入。
WM_THEMECHANGED 與 OpenThemeData。TBSTYLE_CUSTOMERASE + NM_CUSTOMDRAW)。