介紹
向IE中添加的自定義菜單,可以被用來執(zhí)行可執(zhí)行文件,腳本語言和COM對象的方法,對于前兩種執(zhí)行方式,相對比較簡單,只需要對注冊表進(jìn)行編程就
可以了,但是能夠執(zhí)行的功能非常有限,而使用COM組件擴(kuò)展IE菜單則相對復(fù)雜,但是能夠執(zhí)行的功能也相對是最強(qiáng)大的,所以下面我就主要介紹基于COM的
菜單擴(kuò)展方式,還要注意的一點(diǎn)是只有IE5及以后的版本才支持菜單的擴(kuò)展。
創(chuàng)建COM組件
對于一個(gè)IE菜單項(xiàng)COM組件來說,它最少需要實(shí)現(xiàn)IOleCommandTargetCOM接口,如果COM組件還想要對當(dāng)前IE中顯示的頁面進(jìn)
行操作的話,就還需要實(shí)現(xiàn)IObjectWithSite接口,對于IObjectWithSite接口,我將在后面的工具條按鈕擴(kuò)展中討論它的實(shí)現(xiàn)。
首先在Delphi中用New | Other命令調(diào)出New Items對話框,然后在ActiveX頁面中選擇創(chuàng)建一個(gè)新的ActiveX
Library,將項(xiàng)目保存為IEMenu.dpr,然后再次調(diào)用New | Other |
ActiveX命令,新建一個(gè)名為TIEHelloWorld的Com
Object對象,然后添加IOleCommandTarget接口的方法實(shí)現(xiàn),完成的類的定義如下:
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
兩
個(gè)方法,其中文檔上說QueryStatus方法會(huì)被IE調(diào)用來獲得當(dāng)前菜單的狀態(tài),我們需要返回OLECMDF_ENABLED或者其它值來表示是否允
許點(diǎn)擊,但是在實(shí)際當(dāng)中,我發(fā)現(xiàn)IE從來沒有調(diào)用過我的菜單擴(kuò)展的QueryStatus方法,不過不管怎么說,還是按正常的來實(shí)現(xiàn)。
function TIEHelloWorld.QueryStatus(CmdGroup: PGUID; cCmds: Cardinal;
prgCmds: POleCmd; CmdText: POleCmdText): HResult;
begin
//允許點(diǎn)擊菜單
prgCmds^.cmdf:=OLECMDF_ENABLED;
Result := S_OK;
end;
當(dāng)用戶點(diǎn)擊菜單后,IE會(huì)調(diào)用IOleCommandTarget接口的Exec方法來執(zhí)行用戶自定義的操作。
function TIEHelloWorld.Exec(CmdGroup: PGUID; nCmdID, nCmdexecopt: DWORD;
const vaIn: OleVariant; var vaOut: OleVariant): HResult;
begin
Result := S_OK;
//nCmdI為0時(shí),表示菜單和工具條按鈕被點(diǎn)擊了
try
ShowMessage('Hello IE');
except
Result:=E_FAIL;
end;
//注意下面的話語句會(huì)導(dǎo)致AV,不知道為什么?
//vaOut := Null;
end;
Exec方法帶有很多參數(shù),其中IE在調(diào)用菜單擴(kuò)展和工具條按鈕擴(kuò)展組件的的Exec方法時(shí),會(huì)設(shè)定nCmdI為0,其它參數(shù)對于我們來說,都不需
要關(guān)心,只要在成功執(zhí)行代碼后,返回S_OK,在失敗時(shí)返回E_Fail就可以了。實(shí)現(xiàn)了IOleCommandTarget接口之后,一個(gè)最簡單的IE
菜單擴(kuò)展就完成了。
注冊組件
要想讓IE在啟動(dòng)后能夠發(fā)現(xiàn)菜單擴(kuò)展COM組件,并加載菜單進(jìn)行顯示,需要在注冊表中填寫一些配置信息。
1、 要在HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Extensions\項(xiàng)目下新建一個(gè)關(guān)鍵字,名為菜單擴(kuò)展的Guid的字符串形式。
2、 然后在新建的HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Extensions\<菜單擴(kuò)展Guid>關(guān)鍵字下再創(chuàng)建一個(gè)名為ClsidExtension的項(xiàng)目,值也為擴(kuò)展的Guid。
3、 然后在HKEY_LOCAL_MACHINE\Software\Microsoft\Internet Explorer\Extensions\<菜單擴(kuò)展Guid>關(guān)鍵字下添加名為MenuText的字符串字段,寫入IE用來顯示菜單擴(kuò)展的菜單項(xiàng)標(biāo)題文本。
4、 我們還可以創(chuàng)建一個(gè)MenuStatusBar,IE會(huì)在鼠標(biāo)停留在我們的擴(kuò)展對應(yīng)的菜單項(xiàng)時(shí),在IE的狀態(tài)條上顯示MenuStatusBar的文本。這個(gè)注冊表項(xiàng)不是必須項(xiàng)目,可以省略。
5、 通常
情況下,IE會(huì)在工具菜單下顯示我們的擴(kuò)展菜單,但是我們也可以創(chuàng)建一個(gè)MenuCustomize字段,設(shè)定其值為help。這時(shí)IE會(huì)將我們的菜單放
到幫助主菜單下面。如果我們的菜單擴(kuò)展是用來向IE中添加上下文幫助的,可以設(shè)定這個(gè)選項(xiàng)。這個(gè)注冊表項(xiàng)同樣也是可以忽略的。
注意:如果將注冊表位置由HKEY_LOCAL_MACHINE改成HKEY_CURRENT_USER,則菜單擴(kuò)展會(huì)對所有該機(jī)器上用戶生效。
為了實(shí)現(xiàn)添加必要的注冊表信息,編寫AddMenuItem方法來實(shí)現(xiàn)注冊功能:
//添加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;
同時(shí)我們還要注銷菜單擴(kuò)展的功能,方法RemoveMenuItem
被用來刪除注冊表項(xiàng),刪除注冊表項(xiàng)是
Guid
來進(jìn)行的,因?yàn)?/code>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派生類來調(diào)用上面的方法實(shí)現(xiàn)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進(jìn)行刪除
RemoveMenuItem(GuidToString(ClassID));
end;
initialization
TIEHelloMenuFactory.Create(ComServer, TIEHelloWorld, Class_IEHelloWorld,
'IEHelloWorld', '', ciMultiInstance, tmApartment);
end.
完成程序后,我們可以在Delphi IDE中使用菜單 Run | Register ActiveX Server和UnRegister ActiveX Server來注冊創(chuàng)建好的菜單擴(kuò)展,然后啟動(dòng)IE,運(yùn)行后的效果示意圖:

總結(jié)
上面我們介紹了如何創(chuàng)建一個(gè)最簡單的菜單擴(kuò)展,接下來我將探討IE擴(kuò)展的一些更為高級的技術(shù)。
新浪微博:http://t.sina.com.cn/androidguy 昵稱:李寧_Lining