打印本文 打印本文 关闭窗口 关闭窗口
Internet Explorer 编程简述(四)“添加到收藏夹”对话框
作者:武汉SEO闵涛  文章来源:敏韬网  点击数1818  更新时间:2009/4/23 10:51:11  文章录入:mintao  责任编辑:mintao
pt:window.external.AddFavorite(''''" + strUrl + "''''," + "''''" + strTitle + "'''');";
  ExecScript(strjs);
}

void CMIEView::ExecScript(CString strjs)
{
  CComQIPtr<IHTMLDocument2>   pHTMLDoc = (IHTMLDocument2*)GetHtmlDocument();
  if ( pHTMLDoc != NULL  )
  {
    CComQIPtr<IHTMLWindow2>   pHTMLWnd;
    pHTMLDoc->get_parentWindow( &pHTMLWnd );
    if ( pHTMLWnd != NULL  )
    {
      CComBSTR bstrjs = strjs.AllocSysString();
      CComBSTR bstrlan = SysAllocString(L"javascript");
      VARIANT varRet;
      pHTMLWnd->execScript(bstrjs, bstrlan, &varRet);
    }
  }
}

先从CHtmlView获得文档的父窗口window对象的指针,再调用其方法execScript来执行脚本(事实上可以执行任意的脚本)。试验发现,这个方法非常有效,不仅窗口是模态的,而且不需要手动创建链接,更重要的是“允许脱机使用”和“自定义”按钮也可以用了。

4、问题仍旧没有解决

执行脚本的方式看起来有效,可一旦我们的程序实现了IDocHostUIHandler接口对WebBrowser进行高级控制,就会发现一旦执行的脚本包含有对“external”对象的调用,就会出现“找不到对象”的脚本错误。原因是当MSHTML解析引擎(并非WebBrowser)检查到宿主实现了IDocHostUIHandler接口,就会调用其GetExternal方法以获得一个用以扩展DOM的自动化接口的引用。

HRESULT IDocHostUIHandler::GetExternal(IDispatch **ppDispatch)

但有时候我们并没有想要扩展DOM,同时我们还希望WebBrowser使用它自己的DOM扩展。糟糕的是GetExternal方法的文档中说这种情况下必须把ppDispatch设置为NULL,换句话说,WebBrowser连它内置的external对象也不用了,那我们的window.external.AddFavorite就变得无处为家了。

我曾多方尝试将WebBrowser内置的external对象找出来,虽然都没有成功,但是解决问题的方法却被我找到了。

5、完美的方案

WebBrowser内置的external对象我们虽然找不到,但它肯定存在,我们只要想办法让WebBrowser自己完成对其调用即可。实现非常简单,找到WebBrowser中包含的“Internet Explorer_Server”窗口的句柄,发一个消息就完成了。下面的代码中假设m_hWndIE就是“Internet Explorer_Server”窗口的句柄。

#define ID_IE_ID_ADDFAV 2261
::SendMessage( m_hWndIE, WM_COMMAND, MAKEWPARAM(LOWORD(ID_IE_ID_ADDFAV), 0x0), 0 );

试一试成果,是不是和在Internet Explorer中选择“添加到收藏夹”的效果一模一样。

至于为什么这样做,后续文章再说。

参考资料
MSDN: Adding Internet Explorer Favorites to Your Application
MSDN: IShellUIHelper Interface
MSDN: external Object
MSDN: IDocHostUIHandler Interface

上一页  [1] [2] 

打印本文 打印本文 关闭窗口 关闭窗口