BHO(Browser Helper Object,瀏覽器輔助對象,簡稱BHO)
BHO是微軟推出的作為瀏覽器對第三方程序員開放交互接口的業界標准,通過簡單的代碼就可以進入瀏覽器領域的“交互接口”(INTERACTIVED Interface)。通過這個接口,程序員可以編寫代碼獲取瀏覽器的行為,比如“后退”、“前進”、“當前頁面”等,利用BHO的交互特性,程序員還可以用代碼控制瀏覽器行為,比如修改替換瀏覽器工具欄,添加自己的程序按鈕等。
--------------引自百度百科 BHO
在vs中創建一個BHO(使用C++),需要以下步驟:
1.新建一個ATL工程,起名為BHODemo
2.工程新建好之后,切換到類視圖,新加一個ATL簡單對象MyBHO,按照向導所示,添加過程中選中支持IObjectWithSite
3.可以看到,生成了一個接口實現類CMyBHO,在其中添加一個繼承的父類:public IDispEventImpl<1 ,CMyBHO,&DIID_DWebBrowserEvents2,&LIBID_SHDocVw,1 ,1 > 和兩個方法
STDMETHOD(SetSite)(IUnknown * pUnkSite); // 覆蓋父類IObjectWithSiteImpl的方法
void STDMETHODCALLTYPE OnDocumentComplete(IDispatch* pDisp, VARIANT* URL);//文檔加載完成時的動作
4.添加事件接收器部分:
BEGIN_SINK_MAP(CMyBHO)
SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
END_SINK_MAP()
此時第一個參數1,要和IDispEventImpl后面參數中的1的數值要保持一致.這樣DISPID_DOCUMENTCOMPLETE消息由IE傳過來到BHO時,才會調用對應的OnDocumentComplete.可以繼承多IDispEventImpl的,但要保證里面第一個參數,即序號不一樣.
5.實現SetSite和OnDocumentComplete
由於暫時還不做更多操作,所以SetSite實現直接調用IObjectWithSiteImpl<CMyBHO>::SetSite(pUnkSite);而OnDocumentComplete先放空.
現在的源文件應該是長這個樣子的:
1: // MyBHO.h : CMyBHO 的聲明
2:
3: #pragma once
4: #include "resource.h" // 主符號
5: #include "ExDispid.h"
6:
7: #include "BHODemo_i.h"
8:
9: #if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
10: #error "Windows CE 平台(如不提供完全 DCOM 支持的 Windows Mobile 平台)上無法正確支持單線程 COM 對象。定義 _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA 可強制 ATL 支持創建單線程 COM 對象實現並允許使用其單線程 COM 對象實現。rgs 文件中的線程模型已被設置為“Free”,原因是該模型是非 DCOM Windows CE 平台支持的唯一線程模型。"
11: #endif
12:
13: using namespace ATL;
14:
15: // CMyBHO
16:
17: class ATL_NO_VTABLE CMyBHO :
18: public CComObjectRootEx<CComSingleThreadModel>,
19: public CComCoClass<CMyBHO, &CLSID_MyBHO>,
20: public IObjectWithSiteImpl<CMyBHO>,
21: public IDispatchImpl<IMyBHO, &IID_IMyBHO, &LIBID_BHODemoLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
22: public IDispEventImpl<1 ,CMyBHO,&DIID_DWebBrowserEvents2,&LIBID_SHDocVw,1 ,1 >
23: {
24: public:
25: CMyBHO()
26: {
27: }
28:
29: DECLARE_REGISTRY_RESOURCEID(IDR_MYBHO)
30:
31: BEGIN_COM_MAP(CMyBHO)
32: COM_INTERFACE_ENTRY(IMyBHO)
33: COM_INTERFACE_ENTRY(IDispatch)
34: COM_INTERFACE_ENTRY(IObjectWithSite)
35: END_COM_MAP()
36:
37: //路由表
38: BEGIN_SINK_MAP(CMyBHO)
39: SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
40: END_SINK_MAP()
41:
42: DECLARE_PROTECT_FINAL_CONSTRUCT()
43:
44: HRESULT FinalConstruct()
45: {
46: return S_OK;
47: }
48:
49: void FinalRelease()
50: {
51: }
52:
53: public:
54: STDMETHOD(SetSite)(IUnknown * pUnkSite); // 覆蓋父類IObjectWithSiteImpl的方法
55: void STDMETHODCALLTYPE OnDocumentComplete(IDispatch* pDisp, VARIANT* URL);//文檔加載完成時的動作
56: };
57:
58: OBJECT_ENTRY_AUTO(__uuidof(MyBHO), CMyBHO)
cpp文件應該是這樣:
1: // MyBHO.cpp : CMyBHO 的實現
2:
3: #include "stdafx.h"
4: #include "MyBHO.h"
5:
6:
7: // CMyBHO
8: // 覆蓋父類IObjectWithSiteImpl的方法
9: STDMETHODIMP CMyBHO::SetSite(IUnknown * pUnkSite)
10: {
11: //調用基類實現。
12: return IObjectWithSiteImpl<CMyBHO>::SetSite(pUnkSite);
13: }
14: void STDMETHODCALLTYPE CMyBHO::OnDocumentComplete(IDispatch* pDisp, VARIANT* URL)//文檔加載完成時的動作
15: {
16: }
6.注冊表文件
修改BHODemo.rgs文件,刪除原先內容,改為:
HKLM
{
NoRemove SOFTWARE
{
NoRemove Microsoft
{
NoRemove Windows
{
NoRemove CurrentVersion
{
NoRemove Explorer
{
NoRemove 'Browser Helper Objects'
{
ForceRemove {E3C599B7-EB1D-462B-9ED8-D3924EF51BE9} = s 'BHO Demo Class'
{
val NoExplorer = d '1'
}
}
}
}
}
}
}
}
其中ForceRemove 后面的值是抄的idl文件中MyBHO的GUID的值.
7.編譯,然后打開IE就能看到是否啟用BHODemo的提示了.win7下編譯可能會出錯,提示權限問題.這個時候,需要以管理員權限運行vs才行的.
卸載:直接去工程debug目錄中regsvr32 /u BHODemo.dll就行了.同樣要注意win7下的權限問題.

