除了可以向IE中添加自定義菜單外,我們還可以向IE的工具條上添加自定義的按鈕。自定義按鈕同自定義菜單COM擴展的實現幾乎一樣, 除了在注冊時需要添加的注冊表項不同。 注意:同菜單擴展一樣,自定義的按鈕擴展也必須是IE5及以后的版本才支持。 ? 創建COM組件? 下面我們要創建的IE工具條按鈕要稍微復雜一些,當點擊時,不再只是顯示一個簡單的對話框了,而是讓當前瀏覽器瀏覽我的個人網站 http://hubdog.csdn.net。同前一節一樣, 首先創建ActiveX Library,保存為IEButton.dpr,然后再新建一個名為TIEHomeButton的 COM Object,保存向導生成的文件為CIEButton.pas。 ? 同樣的按鈕擴展也需要實現IOleCommandTarget接口,同時為了能夠調用IE的功能,能調用瀏覽器瀏覽指定的網址,我們還需要實現 IObjectWithSite接口。完成的類的定義如下:
type
? TIEHomeButton = class(TComObject, IOleCommandTarget, IObjectWithSite)
? private
??? ShellBrowser: IShellBrowser;
??? IE:IWebBrowser;
? protected
??? //IOleCommandTarget接口定義
??? function QueryStatus(CmdGroup: PGUID; cCmds: Cardinal;
????? prgCmds: POleCmd; CmdText: POleCmdText): HResult; stdcall;
??? function Exec(CmdGroup: PGUID; nCmdID, nCmdexecopt: DWORD;
????? const vaIn: OleVariant; var vaOut: OleVariant): HResult; stdcall;
??? //IObjectWithSite接口定義
??? function SetSite(const pUnkSite: IUnknown): HResult; stdcall;
??? function GetSite(const riid: TIID; out site: IUnknown): HResult; stdcall;
? end;
?
?
其中IObjectWithSite接口有SetSite和GetSite方法。其中IE會在第一次加載工具條按鈕擴展時調用SetSite,將瀏覽器的IShellBrowser作為pUnkSite參數傳遞進來, 我們可以從pUnkSite參數獲得IServiceProvider接口,并調用IServiceProvider接口的QueryService獲得瀏覽器的IWebBrower2接口,然后將IE的接口保存起來,后 面在點擊按鈕時,
我們需要調用IWebBrowser2接口的Navigate方法瀏覽我的哈巴狗的小窩網站。 ?
function TIEHomeButton.SetSite(const pUnkSite: IInterface): HResult;
var
? Service:IServiceProvider;
begin
? ShellBrowser := pUnkSite as IShellBrowser;
? Service:=ShellBrowser as IServiceProvider;
? Service.QueryService(IWebBrowserApp,IWebBrowser2, IE);
? Result := S_OK;
end;
?
IE同時還會不時的調用GetSite方法來從我們保存的pUnkSite接口獲得指定的riid的接口,
function TIEHomeButton.GetSite(const riid: TIID;
? out site: IInterface): HResult;
begin
? if Supports(ShellBrowser, riid, site) then
??? Result := S_OK
? else
??? Result := E_NOTIMPL;
end;
?
如果pUnkSite指針支持該接口,則返回S_OK,否則返回E_ NOTIMPL
表示不支持該接口。
最后,我們需要在
IOleCommandTarget
接口中實現
Exec
方法來執行瀏覽網站的功能,
IWebBrowser2接口的Navigate方法可以多個參數, 這里我們只需要指定要瀏覽的Url就可以了,其它參數都設置為空(使用EmptyParam預定義值)。
function TIEHomeButton.Exec(CmdGroup: PGUID; nCmdID, nCmdexecopt: DWORD;
? const vaIn: OleVariant; var vaOut: OleVariant): HResult;
begin
? Result := S_OK;
? IE.Navigate(''http://hubdog.csdn.net'', emptyParam,emptyParam,emptyParam,emptyParam);
end;
?
注冊擴展
?
要想讓IE能夠在啟動后正確顯示自定義的工具條按鈕擴展,需要在注冊表中填寫一些配置信息。
1.???????? 首先要在HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Extensions\項目下新建一個關鍵字,名為擴展的Guid的字符串形式。
2.???????? 然后在新建的HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Extensions\<擴展的Guid>關鍵字下再創建一個名為CLSID 項目,設定值為{1FBA04EE-3024-11d2-8F1F-0000F87ABD16}。
3.???????? 然后在HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Extensions\<擴展Guid>關鍵字下添加名為ClsidExtension的字段,這回值為按鈕擴展的Guid的字符串形式。
4.???????? 默認時,一個新加的擴展按鈕不會馬上顯示在工具條上,但是我們可以在HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Extensions\<擴展Guid>關鍵字下添加Default Visible字段,并設定其值為Yes,這樣IE啟動時會自動顯示我們添加的按鈕,但是要注意如果用戶在添加按鈕前使用了工具條 右鍵菜單中的自定義…命令調整過工具條按鈕的顯示設置,則我們的擴展按鈕不會自動出現了,必須是通過自定義對話框來手工添加或者調用重置按鈕恢復默認設置來顯示添加的按鈕,見下圖:

\Extensions\<擴展Guid>關鍵字下添加ButtonText項目,設定其值為按鈕的標題。同時按鈕還需要指定兩個
圖標,一個是熱點圖標當鼠標停留在按鈕上時顯示,一個正常圖標用于平時顯示。圖標的文件和路徑需要寫到
HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Extensions\<擴展Guid>關鍵字下的HotIcon和
Icon字段中,值對應于Ico文件,或者可執行文件中的圖標資源,如果圖標是可執行文件的資源,還需要指定
圖標資源索引值。結果示例如下:C:\PROGRA~1\AbcSoft\IEPlugin.dll,209或者 c:\IE.ico ?創建工具條圖標?工具條需要的圖標文件是有一定要求的。首先是尺寸要求,每個按鈕都需要提供20X20和16X16個像素的圖標,其中
20X20的大圖標用于平時顯示, 16X16的圖標是用于IE處于全屏幕顯示狀態時的界面顯示,見下表示例:
大小(像素) | 示例 |
20x20 | ![]() |
16x16 | ![]() |
對應的圖標為灰度圖標。 同時微軟推薦提供的圖標即有256色的,也有16色的。這里為了簡便起見,我只使用一個圖
標用于熱點和正常顯示。 圖標的創建可以使用專業的圖標設計器來創建,不推薦使用Delphi自帶的Image Editor工具,因為Image Editor只能
創建16X16, 32X32大小的圖標, 不能創建20X20大小的圖標。我一般是使用Icon Cool Editor來創建圖標。 這就是我創建的20X20的圖標

編寫一個資源腳本文件Home.rc: 1234?????? ICON?? Home.ICO 注意:這里我使用1234作為圖標的標識而不是使用一個更好記的文本串比如Home,是因為IE只能使用數字標識的圖標
作為按鈕的圖標。使用brcc32 編譯Home.rc為Home.res。注意,在IEButton.dpr中已經有了
{$R *.RES}這句話表示編
譯COM Server時會將所有的資源文件編譯進生成的DLL中。
?
注冊過程
接下來是編寫后的注冊代碼,都是一些對注冊表的操作,注意刪除時是根據Guid進行刪除的,因為Guid是唯一的值:
//添加工具條按鈕
procedure AddToolbarBtn(Visible: Boolean; BtnText, HotIcon,
? Icon, Guid: string);
var
? Reg: TRegistry;
begin
? Reg := TRegistry.Create;
? with Reg do
? try
??? RootKey := HKEY_LOCAL_MACHINE;
??? OpenKey(''\Software\Microsoft\Internet Explorer\Extensions\'' + Guid, True);
??? if Visible then
????? WriteString(''Default Visible'', ''Yes'')
??? else
????? WriteString(''Default Visible'', ''No'');
??? WriteString(''ButtonText'', BtnText);
??? WriteString(''HotIcon'', HotIcon);
??? WriteString(''Icon'', Icon);
??? WriteString(''CLSID'', ''{1FBA04EE-3024-11d2-8F1F-0000F87ABD16}'');
??? WriteString(''ClsidExtension'', Guid);
??? CloseKey;
? finally
??? Free;
? end;
end;
?
//按Guid刪除按鈕
procedure RemoveToolbarBtn(Guid: string);
var
? Reg: TRegistry;
begin
? Reg := TRegistry.Create;
? with Reg do
? begin
??? RootKey := HKEY_LOCAL_MACHINE;
??? DeleteKey(''\Software\Microsoft\Internet Explorer\Extensions\'' + Guid);
??? free;
? end;
end;
然后編寫COM組件工廠類,調用注冊和刪除注冊表項的方法來實現COM組件的注冊和反注冊:
type
? TIEHomeButtonFactory = class(TComObjectFactory)
? public
??? procedure UpdateRegistry(Register: Boolean); override;
? end;
…
function GetDllName: string;
var
? Buffer: array[0..261] of Char;
begin
? GetModuleFileName(HInstance, Buffer, SizeOf(Buffer));
? Result := string(Buffer);
end;
?
procedure TIEHomeButtonFactory.UpdateRegistry(Register: Boolean);
begin
? inherited;
? if Register then
??? AddToolbarBtn(true, ''HomeButton'', GetDllName+'',1234'', GetDllName+'',1234'', GuidToString(classid))
? else
??? RemoveToolbarBtn(GuidToString(classid));
end;
上面的
GetDllName
函數會返回編譯后的
Dll
名稱,在
Dll
名稱加上
'',1234''
表示使用
Dll
中標識為
1234
的圖標作為
按鈕圖標,這里為了簡便起見,
HotIcon
和
Icon
使用的是同一個圖標。
至此,我們的按鈕擴展算是大功告成了,注冊擴展后,運行
IE
,點擊我們的按鈕,效果如下:
