您的位置:首页 > 编程语言 > Delphi

使用Delphi开发IE右键菜单扩展

2020-02-16 16:32 453 查看

介绍

 IE除了允许我们添加自定义的主菜单外,还允许在右键菜单中添加自定义的菜单,。很多著名的网络软件如网络蚂蚁,、网际快车等都在右键菜单中添加了可以用来下载文件的快捷菜单。IE的右键菜单扩展同其它COM扩展不太一样,其它扩展只要在注册表中填写一定的配置信息就可以使用了,而右键菜单扩展必须由一个JavaScript脚本来创建并调用其中的方法。由于我们的COM组件必须能从脚本语言中创建,因此右键菜单扩展的必须是一个Automation(自动化)组件,也就是说除了IUnknown接口外,还必须支持IDispatch接口。幸好,Delphi提供了内置的自动化COM组件的支持,我们只需要从TAutoObject而不是标准的TComObject派生COM组件就可以了。

  经常使用IE复制粘贴网页上的信息,我发现IE右键菜单中的复制命令不是很方便,比如当在一个超链接上激活右键菜单,会发现只有复制快捷方式可以使用,而复制菜单为灰色被禁用状态,而有时我不仅想复制超链接本身,还想复制它的文本,这时我只能是选中链接的文本,然后再点复制,这很不方便。下面我们就来创建一个右键菜单扩展,允许复制超级链接的文本。

创建COM组件

新建一个ActiveX Library项目,保存为IEContext.dpr,然后使用命令 File | New … | ActiveX | Automation Object创建一个名为TIEContextMenu的自动化对象,保存为CIEContextMenu.pas文件。接下来选中Tools | Environment Options命令,激活IDE配置管理界面,切换到Type Library页面,设定类型库语言为Pascal,见下图:

设定为Language选项为Pascal后,则Type Library编辑器会使用我们熟悉的Pascal语言而不是IDL语言来描述COM的接口定义。

然后使用View | Type Library激活COM组件的类型库编辑器,添加接口方法CopyUrlText,如下图所示:

 

CopyUrlText将被用来把连接只有一个参数,就是UrlText,这个参数会由后面我们编写的脚本语句传递过来。完成的COM组件实现如下:

type
  TIEContextMenu = class(TAutoObject, IIEContextMenu)
protected
    procedure CopyUrlText(const UrlText: WideString); safecall;
  end;
implementation
uses ComServ, Clipbrd, Dialogs, Sysutils, Windows, Registry;
procedure TIEContextMenu.CopyUrlText(const UrlText: WideString);
begin
  //将链接文本复制到剪贴板上
  Clipboard.AsText:=UrlText;
end;
注册扩展

要想使右键菜单扩展生效,必须填写下列注册表项:

1.         在HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\MenuExt关键字下添加内容为要创建的右键扩展菜单项的标题文本关键字。文本中可以包含&字符用来指定菜单的快捷方式。

2.         设定标题文本关键字的默认值为包含脚本语句的html文件,当用户点击菜单项时,IE会执行html文件中的脚本,而我们将在脚本中创建自动化对象,并将链接文本作为参数调用自动化对象的方法。

3.         复制链接文本只对链接有意义,而对于其它html页面中的元素无意义,我们可以在注册表中HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\MenuExt\<菜单标题>关键字下添加一个可选的二进制值Contexts值来指定菜单扩展显示的上下文。下表是上下文的列表:

上下文

值(16进制)

默认

0x1

图像

0x2

控制

0x4

表格

0x8

文本选区

0x10

锚点

0x20

超级链接属于上下文中的锚点,所以需要设定contexts的值为32(等于16进制的20)。

下面就是实现注册的类工厂的实现:

type
  TIEContextMenuFactory = class(TAutoObjectFactory)
  public
    procedure UpdateRegistry(Register: Boolean); override;
  end;
procedure AddExtMenuItem(MenuText, Url: string; Contexts:DWord);
var
  reg: TRegistry;
begin
  Reg := TRegistry.Create;
  with Reg do try
    RootKey := HKEY_CURRENT_USER;
    OpenKey('\Software\Microsoft\Internet Explorer\MenuExt\' + MenuText, True);
    WriteString('', Url);
    WriteInteger('contexts', contexts);
    CloseKey;
  finally
    Free;
  end;
end;
procedure RemoveExtMenuItem(MenuText: string);
var
  reg: TRegistry;
begin
  Reg := TRegistry.Create;
  with Reg do try
    RootKey := HKEY_CURRENT_USER;
    DeleteKey('\Software\Microsoft\Internet Explorer\MenuExt\' + MenuText);
  finally
    Free;
  end;
end;
procedure TIEContextMenuFactory.UpdateRegistry(Register: Boolean);
begin
  inherited;
  if Register then
    AddExtMenuItem('
¸′复制链接文本', ExtractFilePath(GetDllName)+'copyurl.htm',32)
  else
    RemoveExtMenuItem('
¸′复制链接文本');
end;
initialization
  TIEContextMenuFactory.Create(ComServer, TIEContextMenu, Class_IEContextMenu,
    ciMultiInstance, tmApartment);
end.
脚本语句

完成了COM组件的编写,剩下的任务就是编写驱动COM组件的VBScript语句的编写了,下面是copyurl.htm的内的VBScript的内容:

<script language="VBScript">

Sub CopyLink(UrlText)

       On Error Resume Next

       set CopyUrl=CreateObject("IEContext.IEContextMenu")

       if err<>0 then

              MsgBox("CopyUrl not properly installed!"+ vbCrLf+"Please register CopyUrl ")

       else

              call CopyUrl.CopyUrlText(UrlText)

        end if

end sub

Sub OnContextMenu()

       set srcEvent = external.menuArguments.event

       set EventElement = external.menuArguments.document.elementFromPoint ( srcEvent.clientX, srcEvent.clientY )

       if srcEvent.type = "MenuExtAnchor" then

              set srcAnchor = EventElement

              do until TypeName(srcAnchor)="HTMLAnchorElement"

                     set srcAnchor=srcAnchor.parentElement

              Loop

              Call CopyLink(srcAnchor.innerText)

       elseif srcEvent.type="MenuEx 1b5d9 tUnknown" then

              set srcAnchor = EventElement

              do until TypeName(srcAnchor)="HTMLAnchorElement"

                     set srcAnchor=srcAnchor.parentElement

                     if TypeName(srcAnchor)="Nothing" then

                            Call CopyLink(EventElement.innerText)

                            exit sub

                     end if

              Loop

              Call CopyLink(srcAnchor.innerText)

       elseif 1=1 then

              MsgBox("Unknown Event Source """ + srcEvent.type + """" + vbCrLf + "Please send description of error to hubdog@263.net")

       end if

end sub

call OnContextMenu()

</script>

简单介绍一下脚本的处理流程,当IE加载copyurl.htm时,会自动调用OnContextMenu过程,在这个过程中,我们可以通过变量external.menuArguments获得IE的IDispatch接口,通过external.menuArguments.event可以进一步获得IE的点击事件的信息,包括用户点击的位置(X,Y坐标可以通过ClientX和ClientY属性获得)。同时可以从IE的当前页面中通过external.menuArguments.document.elementFromPoint方法获得被点中的HTML元素,如果元素类型为HTMLAnchorElement,则表示它是一个链接对象,则元素的innerText属性就对应的链接的标题文本,这时就调用CopyLink子过程,在CopyLink中调用CreateObject(‘IEContext.IEContextMenu’) 来创建我们的菜单扩展对象,其中IEContext.IEContextMenu是扩展对象的ProgID,是由项目的名称+去掉T的扩展对象的类名组合出来的。最后将获得的Url文本作为参数调用扩展对象的CopyUrlText就可以了,菜单对象会完成将文本放到系统的剪贴板中的工作。

总结

       使用菜单命令Run | Register ActiveX Server注册复制链接文本扩展,然后打开光盘中的download.htm文本,选中一个链接,点击右键菜单,执行“复制链接文本”后,将复制的结果粘贴到记事本中,然后在执行复制快捷方式,同样将复制的结果粘贴到剪贴板中,得到的结果见下图:

转载于:https://www.cnblogs.com/onroad/archive/2009/08/28/1556048.html

  • 点赞
  • 收藏
  • 分享
  • 文章举报
dimi3594 发布了0 篇原创文章 · 获赞 0 · 访问量 169 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: