分享

浏览器集成教学 在你的应用程序中集成WebBrowser控件 - Visual C - 第七城市

 DavinTang 2011-03-11

在你的应用程序中集成WebBrowser控件

2007-2-17来源:网络 作者:Sanda 点击: 380
口都派生自IDispatch,并且是应用程序必须实现的事件处理器,用于从一个对象接受事件。要使用这些处理器对象,你需要对对象请求 IConnectionPointContainer接口,在这些中的一个位置注册。只要你有了连接点容器,你就可以在对象和你的事件处理器之间建立连 接。当事件发生的时候,对象将向提供的处理器发送事件。你至少要了解下列三个分发接口:

    DIID_DWebBrowser事件2接口允许你监控WebBrowser控件产生的事件。一个特别重要的事件是 DISPID_NAVIGATECOMPLETE,通知它的宿主文档完全被WebBrowser控件建立。只要这个事件被触 发,IWebBrowser2::get_Document方法就会返回一个指向合法的DHTML文档的接口指针。

    有了DIID_HTMLDocument事件接口,一个应用程序可以接收DHTML文档对象触发的事件,例如onmouseover、 onmousemove、或者onclick。

    第三个接口是DIID_HTMLWindow事件。这个DIID_HTMLWindow事件提供的事件被DHTML对象模型中的窗口触发。 这些事件的例子包含OnLoad、 OnUnload、 OnFocus和OnBlur。

    其他两个重要的接口ICustomDoc和IDocHostUIHandler允许你自定义Internet Explorer用户界面的装饰,以及扩展DHTML对象模型。

    ICustomDoc接口被HTML文档对象实现,允许WebBrowser控件宿主设置它的IDocHostUIHandler接口。通常 Internet Explorer将调用宿主的Client Site的QueryInterface方法获得IDocHostUIHandler接口。但是,如果宿主不支持IOleClientSite接口或者为 了保存这个指针以避免重复调用QueryInterface,可以通过ICustomDoc显式地设置HTML对象的IDocHostUIHandler 接口。

    IDocHostUIHandler 接口可选地被WebBrowser控件的宿主程序实现。通过实现这个接口,宿主程序可以替换Internet Explorer 4.0使用的菜单、工具栏和上下文菜单。当WebBrowser需要访问用户界面(比如窗口大小),或者当它需要解析DHTML窗口对象的 External属性的时候,WebBrowser控件将查询宿主程序的IOleClientSite接口的这个接口(除非它已经被显式地设置)。

    控件宿主也可以通过给脚本引擎提供一个代表宿主程序的外部的自动化对象来扩展DHTML对象模型。脚本中对这个外部对象的引用被脚本引擎解析,发动一个对 WebBrowser宿主应用程序的IDocHostUIHandler接口的查询。然后脚本引擎调用这个接口的get_External方法,宿主应用 程序用这个调用返回一个自动化对象的分发接口。下一步,脚本引擎将通过通常的COM自动化分发方法触发这个对象的方法。
 

(译者注:MFC7中对CHtmlView的增强主要是把这两个接口的实现改成虚函数,并且修复了MFC6中CHtmlView的内存泄漏 问题,而且产生了比如Unicode支持之类的新的问题,以及隐藏了大量细节而可能造成的误解。虽然我很赞同这个对应用程序的简洁性大有好处的改进,但是 如果把CDHtmlDialog里面大堆的DDX函数也包含在这个类里面会更好些)



重用WebBrowser控件以集成DHTML

    在你的程序中完全实现Internet Explorer集成的万里长征第一步是包含WebBrowser控件。WebBrowser控件是一个ActiveX控件,所以你只需要让你的应用程序 能够集成ActiveX组件。关于提供ActiveX控件的容器支持的完整讨论超出了本文的范围,但是你应该很容易找到大量合适的文档。在示例程序 中,ActiveX控件容器接口的支持由MFC处理。

(译者注:不管你喜不喜欢MFC,它的源代码都值得一看。查看MFC的源代码有助于了解细节性问题)

    本文的示例实现了一个基于表单的应用程序,提供给用户两个屏幕。第一个表单允许用户输入属性和值,提供用户一个 选择,按一个按钮浏览到一个显示前面输入的属性的表单。这个报表表单有一个功能是点击一个按钮,返回数据输入表单。

    输入表单的基本功能是通过DHTML和一些内嵌VBScript实现的。应用程序本身提供DHTML对象模型的一个扩展,表示两个DHTML表单。这个扩 展允许表单中的脚本从应用程序中保存和获取属性/值的配对。这是应用程序中一个比较有趣的部分,因为脚本扩展使得一个基于Web的应用程序用这个客户端环 境来在服务器 端保存的网页之间保持状态。

    示例应用程序演示了如何从底层DHTML文档对象截获事件,跟踪用户和DHTML表单上的元素的交互。用户在文档上移动鼠标的时候,应用程序截获onmouseover和onmouseout事件来显示当前鼠标下面HTML元素的的标签名和值。

    示例还应用程序演示了如何截获Internet Explorer的默认行为来在用户右击表单时显示一个自定义的上下文菜单。应用程序捕获了这个事件,并且“短路”了菜单的显示,有效 地对用户隐藏了Internet Explorer正被用于提供显示的事实。

     一个最后的架构问题包含在示例的解释中。和Microsoft Outlook 98一样,本示例应用程序显示HTML,但是不真正从一个Web服务器获得内容。实际上,示例应用程序(而且,我假定Outlook 98)从资源获得它的表单。WebBrowser控件能够通过一个简单的目标URL改变,从Win32映像文件提取资源。作为的URL的以http:// 开始的替代品,一个示例应用程序请求的URL以res://开始。 这通知WebBrowser控件在一个可执行文件内查找资源数据。示例应用程序使用的URL格式是http://<exepath> /<资源名>(译者注:原文有误,应为res://<exepath>/<资源名>,更多信息可以在 Internet Development SDK中的Predefined Protocols部分找到),这里<exepath>是应用程序通过GetModuleFileName在初始化的时候获得的。HTML表 单是简单的ASCII文件,作为自定义资源包含在资源中。资源可以用任何方式命名,不必和实际上的文件名字一致。


添加和删除属性
  图8显示了示例应用程序运行中的主屏幕。注意系统提供的优雅的DHTML图形(我从Outlook 98的一个模板借用了笔记本主题)。表单允许用户通过在编辑区域输入数据,然后按下添加/删除按钮来输入属性/值的配对。按钮在表单中执行图9所示的脚 本。在提供的示例中,用户成功的输入了一个"a,1"的属性/值的配对,并且一个确认消息框被显示。

    图10显示了用户输入一些属性/值的配对之后,按下列表属性按钮的结果。当按钮被按下时,主表单的脚本捕获了按钮的onclick事件,并且调用window.navigate方法移动WebBrowser控件到属性报告表单。

    属性报告页面由图11所示的HTML产生的。这个表单包含一个加载时执行的内嵌脚本。脚本在示例中调用,并且基于用户输入的数据,动态产生一个表格。

在DHTML对象模型中截获事件
    只要你有使得控件工作和显示HTML的代码,你就可以开始监控各种对象的事件。示例应用程序通过建立以下三个对象的事件处理器来完成这个工作,WebBrowser、IHTMLDocument2、和IHTMLWindow2。

    在这些接口上建立事件处理器遵循标准的建立连接点的COM过程。例如,示例程序通过IHTMLDocument2 建立了一个到HTML文档对象的连接。图12显示了本示例的代码片断,连接事件处理器到HTML文档对象(IHTMLDocument2),可以处理来自 HTML文档对象的事件。这个代码 在WebBrowser 组件触发NavigateComplete事件时执行,意味着一个新的HTML文档对象可用。

    对com_util::establish_connection_point的调用做了建立连接点的工作。这个函数尝试用4个参数——一个需要连接到的 对象的接口指针、想建立的连接的类型,实际上的处理器的指针,以及一个用于设置表示这个连接的Cookie的地方——来建立连接。

    一旦连接点被建立,事件将从文档对象流动到指定的处理器。图13显示了html_document的处理器的Invoke方法,以及它如何映射 DISPID到C++ html_document对象的方法调用。html_document基类的所有事件处理方法最初都返回E_NOTIMPL。你必须重载这个类的成员函 数来提供需要的功能。

(译者注:MFC中CHtmlView的虚函数成员基本上就是干这个的,但是有时候可能吃力不讨好,比如DownloadComplete事件的虚函数方式缺少事件的一个参数,以至于我经常自己捕获这个事件,而覆盖掉CHtmlView的事件处理)

    这正好就是my_document类作的事情。my_document重载了来自于底层的DHTML文档对象的onmouseover和 onmouseout事件。my_document::onmouseover方法(参见图14)最重要,因为它显示了如何获得显示文档的窗口。它也显示 了如何从窗口获得描述onmouseover事件的事件对象。从这个事件对象,可以获得表示文档中鼠标移动到的真正的html_element对象。从 html_element对象,示例应用程序获得了元素的标签名字和ID,而且在状态栏显示它。


扩展DHTML对象模型
    扩展DHTML对象模型的功能可以被证明是加入到WebBrowser控件的功能之中最重要的特性。可以用脚本访问的DHTML对象模型暴露了各种对象给代码,无论代码是什么脚本语言。其中一个对象,名字是window,表示显示当前文档的窗口。

    window对象具有一个名字是exte

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多