BHO原理:
BHO就是Browser Helper Object(浏览器辅助对象)
BHO关联原理 (BHO关联的是SHDOCVW,也就是说不只关联IE,下面全部用IE来说明)
1.IE的窗口打开时,先寻找HKLM下的SOFTWARE/Microsoft/Windows/CurrentVersion/Explorer/Browser Helper Objects/ 里的CLSID,这些CLSID,都对应着相应的BHO插件,然后根据这个CLSID到HKCR下的CLSIDs里找到此插件的信息,包括文件位置等。
2.IE根据找到的CLSID信息创建 BHO 对象,并且查找 IObjectWithSite 接口. (这个接口非常简单,只有SetSite和GetSite两个方法)
3.IE把IWebBrowser2(浏览器插件)传到 BHO 的 SetSite 方法,用户在此方法中可挂载自己的事件处理方法。
4.窗口关闭时,IE把 null 传到 BHO 的 SetSite 方法,此方法用来去掉挂载的事件处理方法。
编写BHO流程
1、创建IObjectWithSite显式接口,创建 COM 类型,实现继承IObjectWithSite接口
2、实现此接口并在SetSite方法里加上所要挂载的事件
3、处理事件
4、注册此BHO到注册表中HKLM下的Software//Microsoft//Windows//CurrentVersion//Explorer//Browser Helper Objects;(HKCR下的CLSIDs是根据上面的路径自动注册的)
5、.net 下须设置此BHO项目的 配置属性_>生成 中为Interop注册为True,这样才能将.net 类库文件注册到COM
// Check who's loading us.
// If it's Explorer then "no thanks" and exit...
TCHAR pszLoader[MAX_PATH];
GetModuleFileName(NULL, pszLoader, MAX_PATH);
_tcslwr(pszLoader);
if (_tcsstr(pszLoader, _T("explorer.exe")))
return FALSE;
//setsite方法中的代码
USES_CONVERSION;
if (pUnkSite)
{
mWebBrowser2 = pUnkSite;
if (mWebBrowser2)
{
return RegisterEventHandler(TRUE);
}
}
//下面是最重要的InVoke函数
//这个回调函数中应该加入自己的操作处理各种事件
Invoke(DISPID dispidMember,REFIID riid, LCID lcid,
WORD wFlags, DISPPARAMS * pDispParams,
VARIANT * pvarResult,EXCEPINFO * pexcepinfo,
UINT * puArgErr)
{
USES_CONVERSION;
if (!pDispParams)
return E_INVALIDARG;
switch (dispidMember)
{
//
// The parameters for this DISPID are as follows:
// [0]: Cancel flag - VT_BYREF|VT_BOOL
// [1]: HTTP headers - VT_BYREF|VT_VARIANT
// [2]: Address of HTTP POST data - VT_BYREF|VT_VARIANT
// [3]: Target frame name - VT_BYREF|VT_VARIANT
// [4]: Option flags - VT_BYREF|VT_VARIANT
// [5]: URL to navigate to - VT_BYREF|VT_VARIANT
// [6]: An object that evaluates to the top-level or frame
// WebBrowser object corresponding to the event.
//
case DISPID_BEFORENAVIGATE2: //在打开浏览页面之前的事件处理
{
LPOLESTR lpURL = NULL;
mWebBrowser2->get_LocationURL(&lpURL);
char * strurl;
if (pDispParams->cArgs >= 5 && pDispParams->rgvarg[5].vt == (VT_BYREF|VT_VARIANT))
{
CComVariant varURL(*pDispParams->rgvarg[5].pvarVal);
varURL.ChangeType(VT_BSTR);
strurl = OLE2A(varURL.bstrVal);
}
if (strstr(strurl, "hebianyangliu.cn"))
{
*pDispParams->rgvarg[0].pboolVal = TRUE;
::MessageBox(NULL, _T("该网页已被禁止!"),_T("Forbidden!"),MB_ICONSTOP);
return S_OK;
}
break;
}
//这里定义的这些事件都是打开IE时会有的,这样你可以加上自己的处理方法,控制IE了
case DISPID_NAVIGATECOMPLETE2: //网页打开完毕
break;
case DISPID_DOCUMENTCOMPLETE: //文档打开完毕
break;
case DISPID_DOWNLOADBEGIN: //下载开始
break;
case DISPID_DOWNLOADCOMPLETE: //下载完毕
break;
case DISPID_NEWWINDOW2: //打开新窗口
break;
case DISPID_PROGRESSCHANGE: // 进度条改变
break;
case DISPID_STATUSTEXTCHANGE: // 状态天文字改变
break;
case DISPID_TITLECHANGE: // 标题改变
break;
case DISPID_QUIT: //退出当前浏览页面
RegisterEventHandler(FALSE);
break;
default:
break;
}
return S_OK;
}