介绍
除了可以向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启动时会自动显示我们添加的按钮,但是要注意如果用户在添加按钮前使用了工具条 右键菜单中的自定义…命令调整过工具条按钮的显示设置,则我们的扩展按钮不会自动出现了,必须是通过自定义对话框来手工添加或者调用重置按钮恢复默认设置来显示添加的按钮,见下图:
5. 每个按钮都要有一个显示字符串,在HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer
\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 |
其次有颜色上的要求,当图标处于热点状态时,推荐使用彩色图标,而当图标为正常显示状态时,推荐设定Icon字段
对应的图标为灰度图标。 同时微软推荐提供的图标即有256色的,也有16色的。这里为了简便起见,我只使用一个图
标用于热点和正常显示。
图标的创建可以使用专业的图标设计器来创建,不推荐使用Delphi自带的Image Editor工具,因为Image Editor只能
创建16X16, 32X32大小的图标, 不能创建20X20大小的图标。我一般是使用Icon Cool Editor来创建图标。
这就是我创建的20X20的图标,把它保存为Home.ico,为了能将图标文件编译进最后生成COM Server的Dll文件中,
编写一个资源脚本文件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
,点击我们的按钮,效果如下:
总结
本节中我们主要讨论了如何可以同扩展的宿主IE浏览器进行交互,调用浏览器的功能完成我们的需要,通过调用浏览器的接口我们可以实现一些更加实用更加复杂的功能,后面我们将进一步探讨。