介绍
向IE中添加的自定义菜单,可以被用来执行可执行文件,脚本语言和COM对象的方法,对于前两种执行方式,相对比较简单,只需要对注册表进行编程就可以了,但是能够执行的功能非常有限,而使用COM组件扩展IE菜单则相对复杂,但是能够执行的功能也相对是最强大的,所以下面我就主要介绍基于COM的菜单扩展方式,还要注意的一点是只有IE5及以后的版本才支持菜单的扩展。
创建COM组件
对于一个IE菜单项COM组件来说,它最少需要实现IOleCommandTargetCOM接口,如果COM组件还想要对当前IE中显示的页面进行操作的话,就还需要实现IObjectWithSite接口,对于IObjectWithSite接口,我将在后面的工具条按钮扩展中讨论它的实现。
首先在Delphi中用New | Other命令调出New Items对话框,然后在ActiveX页面中选择创建一个新的ActiveX Library,将项目保存为IEMenu.dpr,然后再次调用New | Other | ActiveX命令,新建一个名为TIEHelloWorld的Com Object对象,然后添加IOleCommandTarget接口的方法实现,完成的类的定义如下:
type  TIEHelloWorld = class(TComObject, IOleCommandTarget)  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;  end;IOleCommandTarget包含QueryStatus和Exec两个方法,其中文档上说QueryStatus方法会被IE调用来获得当前菜单的状态,我们需要返回OLECMDF_ENABLED或者其它值来表示是否允许点击,但是在实际当中,我发现IE从来没有调用过我的菜单扩展的QueryStatus方法,不过不管怎么说,还是按正常的来实现。
function TIEHelloWorld.QueryStatus(CmdGroup: PGUID; cCmds: Cardinal;  prgCmds: POleCmd; CmdText: POleCmdText): HResult;begin  //允许点击菜单  prgCmds^.cmdf:=OLECMDF_ENABLED;  Result := S_OK;end;当用户点击菜单后,IE会调用IOleCommandTarget接口的Exec方法来执行用户自定义的操作。
function TIEHelloWorld.Exec(CmdGroup: PGUID; nCmdID, nCmdexecopt: DWORD;  const vaIn: OleVariant; var vaOut: OleVariant): HResult;begin  Result := S_OK;  //nCmdI为0时,表示菜单和工具条按钮被点击了  try    ShowMessage('Hello IE');  except    Result:=E_FAIL;  end;  //注意下面的话语句会导致AV,不知道为什么?  //vaOut := Null;end;Exec方法带有很多参数,其中IE在调用菜单扩展和工具条按钮扩展组件的的Exec方法时,会设定nCmdI为0,其它参数对于我们来说,都不需要关心,只要在成功执行代码后,返回S_OK,在失败时返回E_Fail就可以了。实现了IOleCommandTarget接口之后,一个最简单的IE菜单扩展就完成了。
注册组件
要想让IE在启动后能够发现菜单扩展COM组件,并加载菜单进行显示,需要在注册表中填写一些配置信息。
1、 要在HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Extensions\项目下新建一个关键字,名为菜单扩展的Guid的字符串形式。
2、 然后在新建的HKEY_LOCAL_MACHINE\Software\Microsoft\Internet  Explorer\Extensions\<菜单扩展Guid>关键字下再创建一个名为ClsidExtension的项目,值也为扩展的Guid。
3、 然后在HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Extensions\<菜单扩展Guid>关键字下添加名为MenuText的字符串字段,写入IE用来显示菜单扩展的菜单项标题文本。
4、 我们还可以创建一个MenuStatusBar,IE会在鼠标停留在我们的扩展对应的菜单项时,在IE的状态条上显示MenuStatusBar的文本。这个注册表项不是必须项目,可以省略。
5、 通常情况下,IE会在工具菜单下显示我们的扩展菜单,但是我们也可以创建一个MenuCustomize字段,设定其值为help。这时IE会将我们的菜单放到帮助主菜单下面。如果我们的菜单扩展是用来向IE中添加上下文帮助的,可以设定这个选项。这个注册表项同样也是可以忽略的。
注意:如果将注册表位置由HKEY_LOCAL_MACHINE改成HKEY_CURRENT_USER,则菜单扩展会对所有该机器上用户生效。
为了实现添加必要的注册表信息,编写AddMenuItem方法来实现注册功能:
//添加IE菜单procedure AddMenuItem(MenuText, StatusBarText, Guid:  string; HelpMenu: Boolean);var  Reg: TRegistry;begin  Reg := TRegistry.Create;  with Reg do  begin    RootKey := HKEY_LOCAL_MACHINE;    OpenKey('\Software\Microsoft\Internet Explorer\Extensions\' + Guid, True);    if HelpMenu then      WriteString('MenuCostumize', 'help');    WriteString('CLSID', '{1FBA04EE-3024-11d2-8F1F-0000F87ABD16}');    WriteString('MenuText', MenuText);    WriteString('MenuStatusBar', StatusBarText);    WriteString('ClsidExtension', Guid);    CloseKey;    CloseKey;    Free;  end;end;同时我们还要注销菜单扩展的功能,方法RemoveMenuItem被用来删除注册表项,删除注册表项是Guid来进行的,因为Guid是可以保证唯一性。
//删除IE菜单procedure RemoveMenuItem(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;
最后,我们定义TIEHelloMenuFactory的TComObjectFactory派生类来调用上面的方法实现COM的组件的注册和注销:
type  TIEHelloMenuFactory = class(TComObjectFactory)  public    procedure UpdateRegistry(Register: Boolean); override;  end;…{ TIEHelloMenuFactory } procedure TIEHelloMenuFactory.UpdateRegistry(Register: Boolean);begin  inherited;  if Register then//添加到Tools菜单下AddMenuItem('HelloIE', 'Hello IE MenuItem', GuidToString(ClassID), False)  else    //Todo: 通过Guid进行删除    RemoveMenuItem(GuidToString(ClassID));end; initialization  TIEHelloMenuFactory.Create(ComServer, TIEHelloWorld, Class_IEHelloWorld,    'IEHelloWorld', '', ciMultiInstance, tmApartment);end.完成程序后,我们可以在Delphi IDE中使用菜单 Run | Register ActiveX Server和UnRegister ActiveX Server来注册创建好的菜单扩展,然后启动IE,运行后的效果示意图:

总结
上面我们介绍了如何创建一个最简单的菜单扩展,接下来我将探讨IE扩展的一些更为高级的技术。
 
                     
                    
                 
                    
                 
 
         
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号