BHO编程

为了钩住浏览器事件或自动化它,Browser Helper Object (BHO)需要建立一个专有并基于COM渠道的通信。缘于此,BHO应该实现IObjectWithSite这个接口,以DLL的形式给IE增加特定功能。用IObjectWithSiteIE将传递一个指向它的IUnknown接口的指针。于是,BHO能保存并查找更多特定的接口,如IWebBrowser2, IDispatchIConnectionPointContainerBHO不仅支持IE而且还会在Windows Explorer中被加载,它的声明周期跟浏览器实例的生命周期一致。IE7为新选项卡创建并销毁一个新的BHOBHO不会被支持WebBrowser control的应用程序或者HTML对话框窗口加载。

 

BHO是动态的,每次Windows ExplorerInternet Explorer的窗口被打开,加载器从注册表读已安装上的BHOCLSID并处理它们。COM分为进程内和进程外组件,用动态链接库实现组件程序时,客户程序调用组件程序来服务会把组件程序装入自己的进程中,这样客户程序和组件程序运行在同一进程控件中,这种叫作进程内组件;实现组件程序另一种形式是EXE程序,它被调用时自己有进程空间,这样客户程序和组件程序运行在不同的进程空间中,这种叫作进程外组件。BHO是一个COM进程内服务器,于是最好的方法是用ATL构建。BHO位于注册表HKLM"SOFTWARE"Microsoft"Windows"CurrentVersion"Explorer"Browser Helper Objects"下。

 

写好BHO后,按F5使得程序Debug运行,这时会弹出”Executable For Debug Session”窗口,在”Executable file name”中选择iexplore.exe。调试时设置断点后,如果不显示信息,如果此时系统是Windows Server,需要Disable Internet Explorer Enhanced Security。在SetSite方法上设置断点,这时你将发现,IE将调用这个方法两次,一次用来建立连接,另一次则是退出。

 

ATL智能指针CComQIPtrCComPtr都能用作管理COM接口指针,都声明在头文件atlbase.h中。CComQIPtr包含了CComPtr的所有功能,但CComQIPtr由于使用了运算符重载会自动调用函数QueryInterface,于是CComQIPtr不能定义IUnknown指针即CComQIPtr<IUnknown>不正确,而应该是CComQIPtr<IUnknown,   &IID_IUnknown>

 

BSTR是一种OLE自动化类型以传输长度在前的数据,BSTR是一个指向以0值结尾('"0')指针;_bstr_t类是BSTR数据类型的C++封装;CComBSTR类是BSTR类型的ATL封装。VARIANT是变量数据类型,定义在OAIDL.H自动化头文件中,适用于引用传递参数类型位置;_variant_t类是VARIANT数据类型的C++封装;CComVariant类是VARIANT类型的ATL封装。ATL程序中CComBSTR转换成CString,需要加入头文件"comutil.h"<iostream>

 

WebBrowser控件能给你的应用程序增加浏览、文档视图和数据下载的能力,使用这一控件的应用程序将使用户能浏览互联网上的网页和本地或网络文件夹。WebBrowser控件同时支持通过点击超链接和URL导航,这个控件维护了一个历史别表,它允许用户前进和后退到以前浏览过的站点、文件夹和文档。WebBrowser控件对应的IE动态链接库是ShDocVw.dll,对应头文件和IDL分别为Exdisp.hExdisp.Idl

 

IE的核心叫Trident渲染引擎也称为MSHTML,它对应的IE动态链接库是mshtml.dllmshtml.dll负责在屏幕上显示网页并处理网页的DOMmshtml.dll解析HTML/CSS文件并且创建内部的DOM树来展现它,mshtml.dll也公开了运行时查看和修改DOM树的API集,mshtml.dll对应头文件和IDL分别是MsHTML.hMsHTML.IdlMSHTML中的接口IHTMLDocument~IHTMLDocument6实现了文档对象的所有成员。

 

头文件ShlGuid.h中定义了IWebBrowser2的接口标识,头文件ExDispid.h中定义了浏览器事件的调度标识符。ATL3.0引入了类IDispEventImplIDispEventImpl仅能处理双接口。事件接收映射被用作建立事件处理,有宏BEGIN_SINK_MAPSINK_ENTRY/SINK_ENTRY_EXEND_SINK_MAP。为了通过事件映射连接到浏览器的事件句柄,需要调用DispEventAdvise;最后调用DispEventUnadvise断开连接。接口DWebBrowserEvents2取代了已废弃的接口DWebBrowserEvents

 

IE事件DocumentComplete在页面被下载和解析之后被激发,但在window.onload事件被触发之前,也不会响应Refresh操作;即使脚本(<script>)中加入DEFER属性(它能使页面完全载入后再执行相当于window.onload),该事件也会被执行,因为脚本在下载后被加载,但在文档完成前。当用户点击Refresh按钮时,DownloadBeginDownloadComplete事件触发;如果用户在页面下载中途点击Stop按钮,这会阻止DownloadComplete事件触发。DownloadBegin事件表明页面正在从服务器传输,通常它后面对应一个DownloadComplete事件,这两个事件成对发生直到该页面和所有它的frame被下载,然后发生事件DocumentComplete。当用户点击Refresh按钮但文档没改变,DownloadComplete事件单独发生,此时其后不会发生事件DocumentComplete。如果一个页面已完成下载,top-level浏览器最后触发事件DocumentComplete,见KB 180366

 

【资源】

Browser Helper Objects: The Browser the Way You Want It

SAMPLE: IEHelper-Attaching to Internet Explorer 4.0 by Using a Browser Helper Object

Building Browser Helper Objects with Visual Studio 2005

Registry Scripting Examples

posted @ 2009-05-04 14:42  jcss  阅读(1356)  评论(0编辑  收藏  举报