定製Internet Explorer擴充介面介面
作者:令狐葉
本文僅介紹IE擴充介面介面,不涉及核心級的進階擴充。
本文大部分資料來自MSDN,MSDN中有更詳細的資料,本文只是摘要編輯。
MSDN中的基本Shell編程從Shell Programmers Guide開始,
IE Shell編程從Browser Extensions Overview開始。(用索引跳轉)
相關資源: 1.本文提及的ATL嚮導都可在www.CodeTools.com,www.Codeguru.com上的ATL,Shell Programming頁下載
要求知識: 基本COM, ATL理解和使用,Shell編程知識。
IE瀏覽器提供了可程式化的對外介面,用於增加自訂的功能的介面介面,自然的,這些介面以COM的形式提供,即:IE定義了一系列的COM介面,你按照它的介面規定實現這些介面,IE運行時調用這些介面,從而完成你的定製介面。另外,有些比較簡單的擴充只需增加註冊表項就可以實現。
基本的擴充介面介面有這麼幾種:
1.添加定製功能表項目到IE操作功能表,如NetAnts, FalshGet。
2.添加定製功能表項目到<工具>菜單下,如NetAnts, FalshGet,MSN Message Service
3.添加定製按鈕到標準工具列,如NetAnts, FalshGet。
4.添加定製的瀏覽欄,工具列。如 記錄,電台欄。
5.捕獲瀏覽器點擊,如NetAnts, FalshGet。
下面分別簡述其實現方法:
1 添加定製功能表項目到IE操作功能表(只需添加註冊表項,以FlashGet為例)
① 在HKEY_CURRENT_USERSoftwareMicrosoftInternet ExplorerMenuExt下添加一個子鍵。
A. 該子鍵名即顯示在操作功能表上的文字,如<使用網際快車下載(&D)>字樣。
B. 該子鍵的預設值為一個網頁檔案的路徑,如Crogram FilesFLASHGETjc_link.htm,該檔案中儲存了你編寫的功能表項目命令激發時將執行的操作的指令碼程式。指令碼將可以利用External.menuArguments 收到當前IE運行狀態的參數。如:<script language="VBScript">
On Error Resume Next
set JetCarCatch=CreateObject("JetCar.Netscape")
If err<>0 then
MsgBox("FlashGet not properly installed!"+ vbCrLf+"lease Install FlashGet again")
Else
set links = external.menuArguments.document.links
ReDim params(links.length*2)
params(0)=external.menuArguments.document.Url
for i = 0 to links.length-1
params(i*2+1)=links(i).href
params(i*2+2)=links(i).innerText
next
JetCarCatch.AddUrlList params
end if
</script>
C. 如果你要控制定製功能表項目的在網頁上的顯示範圍,可以在該子鍵下添加一個Context二進位值,如
FlashGet的0x00000022,表示在點擊圖象或錨點(Archor)時才顯示定製功能表項目。具體的邏輯或位的設定含義如下:
Context 值
預設 0x1
圖象 0x2
控制項 0x4
表 0x8
被選文字 0x10
錨點 0x20
2.添加定製功能表項目到<工具>菜單下 (要求IE5.0)
A. 用Guidgen建立一個GUID,然後用這個GUID為名稱在HKEY_LOCAL_MACHINESoftwareMicrosoftInternet ExplorerExtensions 下建立一個子鍵。
B. 接著在該子鍵下建立一個名為CLSID的字串值”{1FBA04EE-3024-11d2-8F1F-0000F87ABD16}”(固定值)
C. 同理,建立名為MenuText的為功能表項目顯示字串,建立名為MenuStatusBar的為菜單高亮時狀態列顯示的協助字串。另外,如果建立名為MenuCustomize的字串”help”,會將定製的功能表項目移到<協助>主菜單下。
D. 要響應功能表命令有三種實現方式: Exe檔案,指令檔,COM對象。
1. 用Exe檔案只需在子鍵下添加名為Exec的值為Exe檔案的路徑,如Crogram FilesNETANTSNetAnts.exe.
2. 用指令檔只需添加名為script的值為指令檔的路徑。
3. COM實現最複雜,添加名為ClsidExtension字串值為你為此擴充所建立的COM的GUID。
而你的COM對象必須實現IOleCommandTarget介面.
IOleCommandTarget是一個在Windows擴充中很常用的介面。我以為,定義介面其實就是定義協作各方在某一具體方面的協作規定,顧名思義,IOleCommandTarget就是規定了一種在OLE Container與其包容對象之間的命令傳遞的方式。
IOleCommandTarget比較簡單,有兩個要你實現的方法,Exec用於激發命令,執行你定製的功能,QueryStatus用於傳遞命令的解釋性及狀態性描述字串,同註冊表的MenuStatusBar項的功能。從具體的傳遞的參數來講,你所實現的COM對象中的每一個菜單或按鈕命令都以整數標識存在於一個數組中,該數組有一個唯一的GUID標識,使用時依靠命令的整數標識執行相應的操作。更具體的參數含義請見MSDN。
3.添加定製按鈕到標準工具列
基本註冊項同上之菜單,接著你可以
建立ButtonText字串值為按鈕的文字標籤。
建立HotIcon字串值為彩色表徵圖的檔案路徑
建立Icon字串值為灰色表徵圖的檔案路徑
建立Default Visible為是否預設可見,值"YES","NO"。
其命令激發機制與上述定製功能表項目一致,另外還加進一項開啟ExplorerBar功能,將上述2之CLISD項的固定值值改為{E0DD6CAB-2D10-11D2-8F1A-0000F87ABD16}, 在添加BandCLSID字串值為要開啟的瀏覽欄的CLSID,但這樣一來菜單的定製就沒了。
4.添加定製的瀏覽欄,工具列
以上3種定製比較簡單,基本上不用實現COM對象,而要定製瀏覽欄,工具列就一定要實現含有必要介面的COM對象。
有4種可定製的欄,水平瀏覽欄,垂直瀏覽欄,桌面工具列,IE工具列,它們的COM實現基本上是一致的,不同之處僅在於它們在註冊表中的註冊項。除了相同的必要的COM對象類的註冊,還要註冊它們各自的Component Category(組件分類), Windows或IE根據其所註冊的分類決定它們出現的位置,分別註冊為:垂直欄 CATID_InfoBand,水平欄 CATID_CommBand, 案頭欄 CATID_DeskBand,工具列則按另一種註冊方式。
在ATL裡要實現分類註冊是很簡單的,使用宏:
BEGIN_CATEGORY_MAP(你的COM類名稱)
IMPLEMENTED_CATEGORY(分組GUID,如CATID_InfoBand)
END_CATEGORY_MAP()
對於工具列則要在HKEY_LOCAL_MACHINESoftwareMicrosoftInternet ExplorerToolbar下以你實現的COM類的CLSID為名建立一個字串值,可以手工編寫rgs, 如
HKLM
{
NoRemove Software
{
NoRemove Microsoft
{
NoRemove ’Internet Explorer’
{
NoRemove Toolbar
{
val ’{758C84FF-78FD-11D5-91A0-B4078A11DF77}’ = b ’00’
}
}
}
}
}
Band COM實現:
每一個Band對象都要實現三個基本介面IDeskBand, IObjectWithSite, IpersistStream,但不要求實現全部介面方法,而且基本實現是相同的。
其中對IPersistStream的要求最簡單,你只要實現基底介面IPersist的GetClassID,返回你的Band對象的CLSID即可,其餘的直接返回即可。
IObjectWithSite也是一個OLE中常用的介面。Site是位於包容器與被包容對象兩個概念之間的一個對象,通過它,包容器能對被包容對象的細節進行控制,而被包容對象則能執行自己的功能,而IObjectWithSite就是連通二者的Site對象介面。以IE工具列為例,包容器就是IE的那個Rebar, Site代表詳細的在Rebar提供的位置資訊,Site能獲得包容器的資訊,然後你的COM對象要與Site打交道,這又是通過IObjectWithSite來通訊的。
IobjectWithSite包含兩個方法:
SetSite是你的欄視窗與IE串連的最重要的一環,要完成如下工作:
1.事先聲明一個IInputObjectSite指標的類變數,通過該變數可獲得當前網站的資訊,而當你的欄視窗被放置到一新網站時,SetSite就被調用,在執行SetSite時如果先前已保留了一個IInputObjectSite應用,就要先釋放引用。
2.如果傳入的IUnknown為空白,表示欄視窗被移除,直接返回即可。
3.如果傳入的IUnknown不為空白,表示你的欄視窗將被放到一個新Site,這時你要準備建立你的欄視窗,首先向IUnknown索要一個IoleWindow,利用此IOleWindow的GetWindow方法取得父視窗控制代碼,利用此控制代碼正式建立你的視窗欄為它的子視窗,最後向IUnknown索要一個IInputObjectSite對象,並保留其引用到上面所聲明的類變數。
GetSite就是利用儲存的IInputObjectSite指標擷取調用者所要求的介面指標。
最後一個要實現的介面是IDeskBand,它本身只有一個GetBandInfo方法,不過由於IDeskBand擴充於IDockingWindow介面,而IDockingWindow又擴充於IOleWindow, 所以連帶也要實現它們的介面。不過也很簡單。
IOleWindow有兩個方法,在GetWindow中返回你建立的欄視窗的控制代碼,對ContextSensitiveHelp直接返回S_OK.
IDockingWindow有三個方法,在ShowDW中顯示或隱藏你的視窗欄,在CloseDW中銷毀視窗欄,ResizeBorderDW中返回E_NOTIMPL。
IDeskBand的GetBandInfo根據傳入的DESKBANDINFO結構的資訊掩碼,為其賦給相應的資訊值。
另外,如果你要實現欄視窗上的操作功能表,你必須實現IcontextMenu介面,
以上的介面細節,推薦使用RadBytes的RBDeskBand Wizard一下就可搞定,你根本不用去關心它的實現.,你所作的只是實現你的視窗類別。如果使用MFC,你的視窗欄可以直接派生於CWnd或CtoolBar等等;不使用MFC,你可以用ATL的CwindowImpl類來派生視窗類別,如果使用RadBytes的CwindowImpl Wizard就更簡單了,這樣你所做的跟在MFC下沒什麼區別,真的很好用。
5.捕獲瀏覽器點擊,
這個技術牽涉到一個很強大的對象Browser Helper Objects(BHO).
BHO是IE提供的一種可定製控制對象,使用它,你可以監測到IE的各種事件,如 前進,開啟一個URL,下載完畢等;可以完全擷取IE的菜單,工具列並定製它;可以定製當前顯示頁的額外資訊視窗,幾乎是無所不能。
理所當然的,該對象也是你以COM形式提供的,並且每當一個IE進程執行個體運行,你的一個BHO執行個體也隨之產生,並與之關聯。
除了正常的COM註冊,只要在HKLMSOFTWAREMicrosoftWindowsCurrentVersionExplorerBrowser Helper Objects下以你的COM類GUID為名稱建立一個子鍵即可(安裝FlashGet的可在這發現它的註冊項)。
Browser Helper Objects對象必須的介面只有IObjectWithSite,基本原理與上述一致,但實現的功能是不同的。
在SetSite中,你收到的是一個很謙虛的IUnknown,通過它,你可以索要BHO所在IE執行個體的IWebBrowser2介面,使用該介面你可以擷取當前IE的所有資訊,特別是get_Document可獲得頁面的內容。
要截獲某一事件,可以通過上述IWebBrowser2介面索要IConnectionPointerContainer介面,再FindConnectionPoint,找到某一事件對應的出介面的連接點對象,然後用你的COM對象的指標調用Advice註冊。從這個角度,你的COM就是一個接收器外象,所以你要實現IDispatch介面(在ATL工程選dual自動實現),並重載Invoke, 響應IE發給你的事件。如:
CComQIPtr<IWebBrowser2, &IID_IWebBrowser2> m_spWebBrowser2;
CComQIPtr<IConnectionPointContainer, &IID_IConnectionPointContainer> m_spCPC;
CComPtr<IConnectionPoint> spCP;
m_spWebBrowser2 = pUnkSite;//pUnkSite是由SetSite傳入的
m_spCPC = m_spWebBrowser2;//智能指標在賦值時會自動請求對應變數類型的介面
m_spCPC->FindConnectionPoint(DIID_DWebBrowserEvents2, &spCP);//DWebBrowserEvents2是出介面
spCP->Advise(reinterpret_cast<IDispatch*>(this), &m_dwCookie);//this:實現的BHO對象
在IDispatch的OnInvoke中:
if (dispidMember == DISPID_BEFORENAVIGATE2)//傳入開始跳轉事件 DoYourJob();
具體參數見MSDN索引DWebBrowserEvents2.
選用ATL的Internet Explorer Object嚮導很可以方便的產生基本實現架構,你只要重載實現必要的功能就可。更詳細的資料及代碼見MSDN索引Browser Helper Objects,IWebBrowser2。