科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件用VisualStudio2005生成浏览器帮助对象

用VisualStudio2005生成浏览器帮助对象

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

用VisualStudio2005生成浏览器帮助对象

作者:Tony Schreiner,John Sudds 来源:微软 2007年10月16日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
实现基本要素

  “ATL 项目向导”提供了 SetSite 的默认实现。尽管 IObjectWithSite 的接口合约暗示了此方法可以在必要时被反复调用,但确切来说,Internet Explorer 只调用此方法两次;一次用于建立连接,另一次则是在浏览器退出时。特别要提的是,我们 BHO 中的 SetSite 实现将执行以下操作:

  •存储对站点的引用。在初始化期间,浏览器将 IUnknown 指针传递给顶层 WebBrowser 控件,然后 BHO 将对它的引用存储在一个专用成员变量中。

  •释放目前被占用的站点指针。Internet Explorer 传递 NULL 时,BHO 必须释放所有接口引用并且断开与浏览器的连接。

  在处理 SetSite 的过程中,BHO 将根据需要执行其他初始化和非初始化。例如,您可以建立与浏览器的连接点以便接收浏览器事件。

  HelloWorldBHO.h

  在 Visual Studio 的“解决方案资源管理器”中双击打开 HelloWorldBHO.h。

  首先,包含 shlguid.h。此文件定义了 IWebBrowser2 的接口标识符和稍后在项目中使用的事件。

  #include // IID_IWebBrowser2、DIID_DWebBrowserEvents2 等。

  接下来,在 CHelloWorldBHO 类的公共部分声明 SetSite。

  STDMETHOD(SetSite)(IUnknown *pUnkSite);

  STDMETHOD 宏是一个将方法标记为虚拟方法并且确保其具有适用于公共 COM 接口的调用约定的 ATL 约定。它有助于区分 COM 接口和该类中可能存在的其他公共方法。实现成员方法时同样也会使用 STDMETHODIMP 宏。

  最后,在类声明的专用部分中声明某成员变量以存储浏览器站点。

以下是引用片段:
  private:
  CComPtr m_spWebBrowser;
  HelloWorldBHO.cpp
  现在,切换到 HelloWorldBHO.cpp 并为 SetSite 插入以下代码。
  STDMETHODIMP CHelloWorldBHO::SetSite(IUnknown* pUnkSite)
  {
  if (pUnkSite != NULL)
  {
  // 缓存指向 IWebBrowser2 的指针。
  pUnkSite->QueryInterface(IID_IWebBrowser2, (void**)&m_spWebBrowser);
  }
  else
  {
  // 在此释放缓存的指针和其他资源。
  m_spWebBrowser.Release();
  }
  // 返回基类实现
  return IObjectWithSiteImpl::SetSite(pUnkSite);
  }

  初始化期间,浏览器将传递一个对其顶层 IWebBrowser2 接口(我们对其进行缓存处理)的引用。非初始化期间,浏览器将传递 NULL。为避免内存泄漏和循环引用计数,此时释放所有指针和资源非常重要。最后,我们调用基类实现以便它可以履行接口合约的其余部分。

  HelloWorld.cpp

  加载 DLL 后,系统将通过 DLL_PROCESS_ATTACH 通知调用 DllMain 函数。由于 Internet Explorer 大量使用多线程,因此,对 DllMain 的频繁的 DLL_THREAD_ATTACH 和 DLL_THREAD_DETACH 通知会降低扩展和浏览器进程的整体性能。既然该 BHO 不需要线程级的跟踪,我们可以在 DLL_PROCESS_ATTACH 通知期间调用 DisableThreadLibraryCalls 以避免新线程通知的额外开销。

  在 HelloWorld.cpp 中,如下编写 DllMain 函数的代码:

以下是引用片段:
  extern "C" BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
  {
  if (dwReason == DLL_PROCESS_ATTACH)
  {
  DisableThreadLibraryCalls(hInstance);
  }
  return _AtlModule.DllMain(dwReason, lpReserved);
  }

  注册 BHO

  剩下要做的只是将 BHO 的 CLSID 添加到注册表中。此条目会将 DLL 标记为浏览器帮助程序对象,并使 Internet Explorer 在启动时加载 BHO。Visual Studio 可在生成项目时注册 CLSID。

  注意 在 Windows Vista 上,Visual Studio 需要提升的特权才能与注册表进行交互。请确保通过在“开始”菜单中右键单击 Microsoft Visual Studio 2005 并选择“以管理员身份运行”来启动开发环境。

  此 BHO 的 CLSID 可在 HelloWorld.idl 中找到(位于如下所示的代码块中):

以下是引用片段:
  importlib("stdole2.tlb");
  [
  uuid(D2F7E1E3-C9DC-4349-B72C-D5A708D6DD77),
  helpstring("HelloWorldBHO Class")
  ]

  请注意,此文件包含三个 GUID;我们需要的是用于类的 CLSID,而不是用于库的 CLSID 或接口 ID。

  创建自行注册的 BHO:

  1.从 Visual Studio 中的“解决方案资源管理器”打开 HelloWorld.rgs。

  2.将以下代码添加到文件末尾:

以下是引用片段:
  HKLM {
  NoRemove SOFTWARE {
  NoRemove Microsoft {
  NoRemove Windows {
  NoRemove CurrentVersion {
  NoRemove Explorer {
  NoRemove '浏览器帮助程序对象' {
  ForceRemove '{D2F7E1E3-C9DC-4349-B72C-D5A708D6DD77}' = s 'HelloWorldBHO' {
  val 'NoExplorer' = d '1'
  }
  }
  }
  }
  }
  }
  }
  }

  3.将上述 ForceRemove 后面的 GUID 替换为 BHO 的 CLSID(可在 HelloWorld.idl 中找到)。

  切勿替换大括号。

  4.保存文件,然后重新生成解决方案。(按 F6。)

  Visual Studio 将自动注册该对象。

  NoRemove 关键字表示取消注册 BHO 时将不删除该注册表项。除非您指定了此关键字,否则将删除空的注册表项。ForceRemove 关键字表示将删除该注册表项以及它所包含的任何值和子项。ForceRemove 还将导致在注册 BHO 后重新创建该注册表项(如果它已存在)。

  既然此 BHO 专用于 Internet Explorer,那么我们指定 NoExplorer 值以防止 Windows Explorer 加载它。值和类型是什么都不重要,只要 NoExplorer 条目存在,Windows Explorer 就不会加载 BHO。

  现在,您就可以从 Visual Studio 2005 中的“生成”菜单生成解决方案。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章