且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

创建一个BHO

更新时间:2022-09-12 21:01:11

 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下的权限问题.


本文转自leipei博客园博客,原文链接:http://www.cnblogs.com/leipei2352/archive/2012/11/10/2763604.html,如需转载请自行联系原作者