日期:2008-08-06  浏览次数:21220 次

IE里的探索之定制浏览器好助手(中)
(作者:青苹果工作室编译 2001年02月08日 14:00)


检测调用者
  像前面提到的,如果你运行的外壳版本不低于471,BHO 就既能被Internet Explorer又能被Windows Explorer引用。在这个例子里,我们要是涉及一个专对 HTML 页面起作用的助手对象,所以它应该对 Windows Explorer 不起任何作用。一个不想被特定的调用者加载的 DLL 可以在它发现谁是调用者后,简单地在它的 DllMain() 函数中返回 False。当你将 NULL 作为 API 函数 GetModuleFileName() 的第一个参数调用它时,它返回调用 DLL 的模块名。这个参数是你想知道名字的模块的句柄。NULL 表示你想知道调用 DLL 的进程的名字。

  if (dwReason == DLL_PROCESS_ATTACH)

  {

   TCHAR pszLoader[MAX_PATH];

   GetModuleFileName(NULL, pszLoader, MAX_PATH);

   _tcslwr(pszLoader);

   if (_tCSStr(pszLoader, _T("explorer.exe")))

   return FALSE;

  }

  你知道了进程的名字,你就能在它是 Windows Explorer 时退出加载过程。注意采取更严格的淘汰是很危险的。实际上,其它进程可能视为一个正常的原因调用它但被拒绝。第一个受害者是 regsvr32.exe,这个程序用来自动注册对象。如果 你是用不同的测试条件,比如说,只允许 Internet Explorer 可以执行:

   if (!_tCSStr(pszLoader, _T("iexplore.exe")))

  你就不能注册 DLL 了。实际上,当 regsvr32.exe 试图加载 DLL 以调用DllRegisterServer() 函数时,调用被拒绝。

同 WebBrowser 建立联系
  SetSite() 方法是 BHO 进行初始化以及所有只进行一次任务的地方。当你用 Internet Explorer 浏览 URL 时,你需要等待一对事件以确保所需的文档被完全下载并被初始化。只有在这一位置上你能通过可能存在的对象模型安全地访问它的 内容。这表示你需要获得一对指针。第一个是指向 IWebBrowser2 的,它是处理 WebBrowser 对象的接口。第二个指针和事件有关。这个模块必须注册为浏览器的事件监听者,以便能够接收关于下载和文档相关事件的通知。通过使用 ATL 的灵巧指针:

  CComQIPtr<IWebBrowser2, &IID_IWebBrowser2> m_spWebBrowser2;

  CComQIPtr<IConnectionPointContainer,

     &IID_IConnectionPointContainer> m_spCPC;

  源代码类似于:

  HRESULT CViewSource::SetSite(IUnknown *pUnkSite)

  {

   // 获得并保存 IWebBrowser2 指针

   m_spWebBrowser2 = pUnkSite;

   if (m_spWebBrowser2 == NULL)

   return E_INVALIDARG;

   // 获得并保存 IConnectionPointerContainer 指针

   m_spCPC = m_spWebBrowser2;

   if (m_spCPC == NULL)

   return E_POINTER;

   // 获得并保存浏览器的 HWND。另外为以后的使用安装键盘挂钩。

   RetrieveBrowserWindow();

   // 连接到容器以接受事件通知

   return Connect();

  }

  要获得指向 IWebBrowser2 接口的指针,你只需要简单地查询。对事件处理的第一个步骤,获得 IConnectionPointContainer 的指针,也用同样的办法。SetSite() 的代码也查询浏览器的 HWND 并在当前线程上安装键盘挂钩。HWND 以后会被用以移动 Internet Explorer 窗口并改变它的尺寸。那个挂钩,被用以提供一个热键,以方便用户显示或隐藏 HTML 代码窗口。