首页产品库评测行情新闻|手机数码笔记本台式机DIY硬件数字家庭数码相机办公外设|软件下载游戏开发|社区

更多

数码相机
MP4
LCD
机箱
音箱

软件资讯设计 工具 系统 开发 安全 办公 陶吧 IT教育 Vista频道 | 下载中心酷我音乐盒 腾讯QQ
天极网 > 开发频道>用VisualStudio2005生成浏览器帮助对象

用VisualStudio2005生成浏览器帮助对象

2007-02-06 08:04作者:Tony Schreiner,John Sudds出处:微软责任编辑:龙犊

  进行试用

  为了进行快速测试,请在 SetSite 中设置一个断点,然后按 F5 启动调试程序。当出现“调试会话的可执行文件”对话框时,选择“默认的 Web 浏览器”,然后单击“确定”。如果 Internet Explorer 不是您的默认浏览器,则可以浏览查找可执行文件。

  注意 在 Windows Vista 上,Internet Explorer 的“保护模式”功能将启动另一个进程,然后退出,这样会给调试带来一点难度。您可以通过以下两种方式轻松关闭当前会话的“保护模式”:从管理进程(例如 Visual Studio)启动浏览器,或者创建一个本地 HTML 文件并将其指定为 Internet Explorer 的命令行参数。

  浏览器启动时,将加载 BHO 的 DLL。命中断点时,请注意是否设置了 pUnkSite 参数。再次按 F5 以继续加载主页。

  关闭浏览器以验证是否通过 NULL 再次调用了 SetSite。

  对事件做出响应

  既然已经确认了 Internet Explorer 可以加载和运行 BHO,那就让我们在所举示例的基础上再深入一些,将 BHO 扩展到响应浏览器事件。在本部分中,我们介绍如何使用 ATL 为 DocumentComplete(在页面加载后显示一个消息框)实现一个事件处理程序。

  为接到事件通知,BHO 建立一个与浏览器之间的连接点;为响应这些事件,它将实现 IDispatch。根据 DocumentComplete 的文档,该事件有两个参数:pDisp(IDispatch 的指针)和 pUrl。这些参数将作为事件的一部分传递给 IDispatch::Invoke;但手动析取这些事件参数并非一项简单的任务,并且易于出错。幸好 ATL 提供了一个默认实现,可以帮助简化这个事件处理逻辑。

  HelloWorldBHO.h

  首先通过包含 exdispid.h(为浏览器事件定义调度 ID)处理 HelloWorldBHO.h。

  #include // DISPID_DOCUMENTCOMPLETE 等。

  接下来,从 IDispEventImpl 基类进行派生,该基类为处理事件提供了除 Invoke 之外的另一个简单安全的替代方法。IDispEventImpl 与事件汇映射配合工作,以将事件路由到相应的处理程序函数。我们明确说明,想要使用以下类定义(突出显示)处理由 DWebBrowserEvents2 接口定义的事件。

以下是引用片段:
  class ATL_NO_VTABLE CHelloWorldBHO :
  public CComObjectRootEx,
  public CComCoClass,
  public IObjectWithSiteImpl,
  public IDispatchImpl,
  public IDispEventImpl<1, CHelloWorldBHO, &DIID_DWebBrowserEvents2, &LIBID_SHDocVw, 1, 1>

  接下来,添加将事件路由到新的 OnDocumentComplete 事件处理程序方法的 ATL 宏,该事件处理程序方法采用的是 DocumentComplete 事件所定义的相同参数和顺序。将以下代码放置到该类的公共部分。

以下是引用片段:
  BEGIN_SINK_MAP(CHelloWorldBHO)
  SINK_ENTRY_EX(1, DIID_DWebBrowserEvents2, DISPID_DOCUMENTCOMPLETE, OnDocumentComplete)
  END_SINK_MAP()
  // DWebBrowserEvents2
  void STDMETHODCALLTYPE OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL);

  提供给 SINK_ENTRY_EX 宏 (1) 的数字指的是 IDispEventImpl 类定义的第一个参数,在必要时用于区分来自不同接口的事件。另请注意,不能从该事件处理程序返回值;这是因为 Internet Explorer 无论怎样都会忽略从 Invoke 返回的值。

  最后,添加一个专用成员变量,以跟踪各对象是否已建立了与浏览器的连接。

以下是引用片段:
  private:
  BOOL m_fAdvised;
  HelloWorldBHO.cpp

  要通过事件映射将事件处理程序连接到浏览器,可在处理 SetSite 期间调用 DispEventAdvise。同样,使用 DispEventUnadvise 断开连接。

  以下是 SetSite 的新实现:

以下是引用片段:
  STDMETHODIMP CHelloWorldBHO::SetSite(IUnknown* pUnkSite)
  {
  if (pUnkSite != NULL)
  {
  // 缓存指向 IWebBrowser2 的指针。
  HRESULT hr = pUnkSite->QueryInterface(IID_IWebBrowser2, (void **)&m_spWebBrowser);
  if (SUCCEEDED(hr))
  {
  // 注册以从 DWebBrowserEvents2 中汇集事件。
  hr = DispEventAdvise(m_spWebBrowser);
  if (SUCCEEDED(hr))
  {
  m_fAdvised = TRUE;
  }
  }
  }
  else
  {
  // 取消注册事件汇。
  if (m_fAdvised)
  {
  DispEventUnadvise(m_spWebBrowser);
  m_fAdvised = FALSE;
  }
  // 在此释放缓存的指针和其他资源。
  m_spWebBrowser.Release();
  }
  // 调用基类实现。
  return IObjectWithSiteImpl::SetSite(pUnkSite);
  }

  最后,添加一个简单的 OnDocumentComplete 事件处理程序。

以下是引用片段:
  void STDMETHODCALLTYPE CHelloWorldBHO::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL)
  {
  // 从站点检索顶级窗口。
  HWND hwnd;
  HRESULT hr = m_spWebBrowser->get_HWND((LONG_PTR*)&hwnd);
  if (SUCCEEDED(hr))
  {
  // 加载页面时输出消息框。
  MessageBox(hwnd, L"大家好!", L"BHO", MB_OK);
  }
  }

  请注意,消息框会将站点的顶层窗口用作其父窗口,而不仅仅是通过该参数传递 NULL。在 Internet Explorer 6 中,NULL 父窗口并不阻止应用程序,也就是说,在消息框等待用户输入时用户可以继续与浏览器交互。在某些情况下,这会导致浏览器挂起或崩溃。在 BHO 需要显示 UI 的这种少见情况下,应始终通过指定指向父窗口的句柄来确保该对话框为应用程序模态。

关注此文的读者还看过:

返回开发频道首页

软件频道最新更新

热点推荐

IT嘉年华

编辑推荐

软件下载

热门
推荐

网友关注

软件
资料
游戏

装机推荐

文章排行

本周
本月
最新更新
天极服务|关于我们|About us|网站律师|RSS订阅|友情合作|加入我们|天极动态|网站地图|意见反馈|MSN/QQ上看天极
Copyright (C) 1999-2012 Yesky.com, All Rights Reserved 版权所有 天极网络