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] [聊天工具]用Windows98第二版直接共享Internet [系统软件]Internet Explorer 编程简述(繁体版) [系统软件]单击链接后无法打开新的 Internet Explorer 窗口或… [系统软件]delphi2005帮助系统使用了microsoft document exp… [系统软件]对Internet Explorer Web 控件做一点修改 [系统软件]OLE with the internet explorer [系统软件]打造个性化的Internet Explorer [系统软件]3dMax导出.x文件以及3D Explorer [常用软件]微软Internet Explorer 8最新动向 [常用软件]PDF全能管家——PDFExplorer
|