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 代码窗口。
