目前,ActiveX Scripting还不能像我们谈论过的
VBScript和
JavaScript语言那样,成为一种语言(宏或其它形式的语言,本章下一节将讨论
JavaScript语言)。最好将它定义为客户机与
服务器之间的一种
通信方法。实质上,它是Microsoft为OLE自动化起的新名称。说OLE自动化与ActiveX Scripting完全相同也许不够准确,因为Microsoft没有把ActiveX Scripting的能力停留在应用级别上。(大多数Microsoft产品和诸如CorelDRAW之类的一些其它产品,在应用级别上支持OLE自动化!)ActiveX Scripting还包括了Internet。
可移植性问题 本书前面的例子中,MFC AppWizard(应用程序向导)提供了OLE自动化复选框,这一点也许你已注意到。这一复选框,像诸如CorelDRAW 之类的产品一样,向你的应用程序添加相同种类的脚本能力。换言之,可以在本地的机器或
网络中使用脚本能力。但是,这一能力仍然不是完整的ActiveX Scripting,因为它不包括Internet。你仍然需要手工地向Visual
C++应用程序添加这种功能。因为ActiveXScripting 标准还没有最后定下来,所以你看到的仍然是进展中的东西。
既然ActiveX Scripting不是语言,而是通信规范,那么,脚本语言,包括语法,这一类问题就留给了脚本供货商来提供。这一标准的目的在于定义一种方法,使脚本主机可以调用各种脚本引擎,并且用于OLE容器中对象间的通信。从实质上看,脚本更像是可执行代码的大杂烩,它可能含有文本、伪代码,甚至还有原始二进制格式的可执行代码。ActiveX Scripting的实质是,它是基于OLE的、可用于应用程序和Internet的通信媒介。
Web链接 写作本书时,ActiveX Scripting 说明书仍在变动之中。如果打算用ActiveX Scripting作为其它技术的替代或补充,也许要用些时间看一下最新动向。进而,本节并不完全涵盖OLE主机和脚本引擎需要的所有接口方法的调用语法。欲了解目前 ActiveX Scripting说明更多的信息,请查看http://www.microsoft.com/intdev/sdk/docs/olescrpt/要查找有关ActiveX Scripting主机的信息,下列两个站点不错:http://www.microsoft.com/msdn/ sdk/inetsdk/help/wsh/wobj_2.htm和http://www.microsoft.com/msdn/sdk/ inetsdk/help/compdev/scripting/hosts.htm。如果想多了解一些关于建立一个ActiveX Scripting引擎的需求,请查看:http://www.microsoft.com/msdn/sdk/inetsdk/help/compdev/engines/engines.htm。
让我们花点时间定义几个术语。首先,精确地说,什么是脚本主机呢? 它是支持脚本引擎的一种应用程序。定义脚本时,是脚本主机接受这个脚本并向引擎发出命令。ActiveX Scripting主机的最通用的例子是
Internet Explorer 3.0。使用插件可以向Netscape Navigator 添加这种能力。第8章讨论过一种插件棗NCompass ScriptActive。脚本引擎,当然不限于这些产品中的任何一种。你可以在一个定制的浏览器应用程序中建立它,或者在一些应用程序中找到它。例如,很有可能,在不远的将来,Microsoft会使其全部应用程序产品(如MicrosoftWord)都符合这一标准。
一个ActiveX脚本引擎是一个对象,这个对象才真正地对脚本进行解释。对精确的语言语法甚至脚本的形式都没有限制。理论上,写ActiveX 脚本,可使用任意语言,包括
VBScript、Java和JavaScript 。和本节后面要讨论的任何一种 OLE 对象一样,一个ActiveX脚本引擎提供的是特殊接口。另外,可以使用OLE自动化包装工具写出ActiveX脚本引擎(Microsoft计划为ActiveXScripting提供一种特殊形式的OLE自动化包装器)。使用包装器格式的好处是,它保持了代码的短小精炼──这对于浏览器和在线脚本引擎都是理想选择。不利之处是,如果直接写出ActiveX Scripting接口,你将失去对运行时你可以有的名字空间、持久模型以及其它著作元素的控制。
ActiveX Scripting 要求有四种新的接口元素。可选项IActiveScriptSite 和可选项IActiveScriptSite
Windows 接口为主机专用,而IActiveScript和可选项IActiveScriptParse接口则为脚本引擎专用(若不实现IActiveScriptParse,则需要实现某种形式的IPersist接口)。每个接口元素执行下面列出的一种具体功能:
IactiveScriptSite 这个接口的主要目的是为ActiveX Scripting 引擎创建一个站点。这与其它的OLE实现中的容器的概念(idea)相对应──容器容纳的是诸如ActiveX控件之类的东西。因为这是一个容器接口,所以它监测脚本的开始、终止及脚本出错等等一类的事件。
IactiveScriptSiteWindow 任一个提供用户接口的ActiveX Scripting主机,也需要提供本接口(服务器不一定应用它)。实际上,如果需要用于脚本目的的窗口,则也需要实现这一接口。IActiveScriptSiteWindow 提供了两种主要方法(尽管可以提供其它所需的方法):GetWindow()用于创建窗口,EnableModeless( ) 则设置窗口的模式(modal)条件。GetWindow()的功能类似于OLE自动化专用的IOleWindow::GetWindow()函数,而EnableModeless()的功能则类似于IOleInPlaceFrame::EnableModeless()函数。
IactiveScript 这一接口使你与脚本本身一起工作,用它可得到脚本的站点、启动和终止脚本、使用脚本项目、关闭脚本、或者建立线程状态与参数。
IactiveScriptParse 这一接口从脚本主机接受脚本,它使你能创建一个新脚本、 向一个现存脚本中添加原始脚本片段或对一个现存脚本进行分析。
Visual C++提供了一个方便的实用程序,称为OLE/COM Object Viewer(OLE/COM 对象浏览器),使用它可以更详细地看到这些接口(Microsoft 在其Visual C++的最新版本中将名称缩写为OLE View(OLE浏览器))。本书中我们将多次用到这个实用程序,如果你还没有安装的话,应该安装上它。让我们先看一看ActiveX Scripting issue的主机端。和以前提到的一样,Visual C++仍然提供一个OLE自动化接口,这个接口不提供与Internet连接的功能。接着请打开OLE/COM Object Viewer,就会看到一叠文件夹。打开Document Objects(文档对象)文件夹,再打开XYZ Single Document 文件夹,就会看到接口列表,与图9.1类似,这些接口是MFC实现的,建立应用程序时可使用它们。

请注意在左边的窗格中的IOle Window接口已被选中。看一下右边的窗格,可以看到这个接口提供五种方法。进一步研究表明,这些方法之一是GetWindow()。前面提到过,没有IActiveScriptSiteWindow接口,而IOleWindow接口却存在,这意味着你的应用程序支持OLE自动化,而不支持ActiveXScripting。现在,如果你看一下这个列表中的每个其它应用程序,(如果有的话)包括
Office97,就会发现,没有一个应用程序是支持ActiveX Scripting的。
警告 如果在OLE/COM Object Viewer中创建了应用程序或控件的实例,而后没有不释放相应实例,那么就会发生奇怪的事情。例如,你的机器会意外地死机! 每当你查看一个应用程序或控件支持的接口时,就不得不创建一个实例来完成这个操作。通过查看应用程序的名称,也能够知道是否存在一个对象的实例。OLE/COM Object Viewer用粗体显示打开的对象。为了释放你创建的实例,用右键单击对象名(比如是XYZ Single Document),然后在上下文相关菜单中选择 ReleaseInstance(释放实例)即可完成。幸运的是,OLE/COM Object Viewer在你离开该工具时总是会关闭对象的实例,但是如果在查看会话期间机器的
内存开始不够用时,就应该关闭对象的实例。应该记住,每创建一个实例,就要占用一些内存。
客户端对ActiveX Scripting也是支持的,至少在一种初步形式上是这样。释放 XYZ Single Document的实例,然后关闭Document Object 文件夹。接着打开ActiveX Scripting Engine文件夹,可以看到两个项,一个是JavaScript,另一个是VBScript。这两个项都是Internet Explorer支持的,但我们期望看到NetscapeNavigator也支持它们。打开JScript Language(JavaScript)项,可以看到如图9.2所示的典型的接口列表(你的列表也许会稍有不同)。

图9.2 在OLE视图中查看JavaScrip
请留意被选中的项IActiveScript,它是我前面描述过的第一个客户机端接口,在它下面,可以看到IactiveScript-Parse项,它是我前面描述的第二个客户机端接口。这两个元素的存在,意味着Internet Explorer当前把ActiveX Scripting做为一个客户机来支持它。但是,在OLE/COM Object Viewer 的这一部分中却连一个相联系的服务器项都找不到。
让我们对于ActiveX Scripting 的主机与客户机的关系再多说几句。一个ActiveX Scripting会话期,要涉及到三个不同的元素:主机、引擎以及包含代码和控件的窗口(页)。在这三个元素之间建立通信的过程有8个步骤:
1. 主机根据需要装入文档或工程。这不是ActiveX Scripting专用任务,因为任意环境都需要执行这一步。
2. 主机创建一个脚本引擎。通常,它要使用<OBJECT>标记中的PROGID属性,并通过调用CoCreatInstance()来完成这个任务。
3. 然后装入脚本。主机完成这件事的方式有几种。如果脚本存贮为驻留(Persisted)数据,那么,主机就使用引擎的IPersist::Load()把它再次装入内存。如果主机需要装入一个新脚本,那么它就调用IActiveScriptParse::InitNew()或者IPersist::InitNew()创建一个空脚本。把脚本当成文本来维护的主机,然后调用IActiveScriptParse::ParseScriptText()把脚本装入引擎(使用其它格式维护脚本的主机则不得不设计自己的装入方法)。
4. 主机把脚本装入后,必须用实体填入引擎的名字空间。实体可以是窗体、 页或其它文档。主机使用IActiveScript::AddNameItem()方法完成这一任务。显然,它不必装入存贮为脚本驻留内存一部分的那些实体。低级项(比如ActiveX 控件)需要不同的装入技术,主机使用ITypeInfo和IDispatch接口来完成这项工作。
5. 现在,ActiveX 脚本引擎已取得了它需要运行脚本所需的一切。主机发出一个IActiveScript::SetScriptState(SCRIPTSTATE_CONNECTED)调用,这就是让脚本引擎启动脚本。它相当于标准C程序中调用Main()函数。
6. 在脚本引擎真正开始运行脚本之前,它还要先干几件家务活。例如,需要为每个顶级项联系上一个符号。脚本引擎干这件事时使用的是IActiveScriptSite::GetItemInfo()方法。
7. 脚本引擎真正运行脚本之前的最后一个步骤是,在脚本元素与与对象相关联的事件之间建立适当连接。例如,如果存在一个脚本项,它处理一个按钮的onClick (单击)事件,那么脚本引擎就需要在运行脚本之前建立这个连接。脚本引擎使用IConnectionPoint接口完成这一工作。
8. 最后,脚本引擎开始运行脚本,运行脚本时,脚本引擎需要访问与HTML 页上或其它文档中的对象相关联的方法和属性。它使用IDispatch::Invoke()或其它标准的OLE捆绑方法来干这件事。
现在,你对脚本如何工作这一点已有了相当好的理解。让我们快速地看一下,脚本引擎运行时作出反应的几种方式。脚本引擎不只是具有简单的两种操作状态:ON/OFF,实际上它具有好几种状态,使用这些状态,可以确定需要干些什么才能使它运行。(使用 IActiveScript::GetScriptState()方法可以得到当前状态。) 以下列表列出了脚本引擎的各种状态:
Uninitialized(未初始化) 这表明脚本引擎还没有准备好,通常,主机在脚本引擎离开这一状态前,要装入运行脚本所需的脚本和实体。
Initialized(已初始化) 脚本已装入(通常用IPersist ),运行站点已设定(使用IActiveScriptSite),但脚本引擎还没有真正地与一个主机相联系。脚本引擎处于这种状态时,不能运行任何代码。一旦脚本引擎进入已启动状态,则由IActiveScriptParse::ParseScriptText()执行的代码将开始运行。
Started(已启动) 这是一种过渡状态。从这种状态使用IDispatch就能运行代码了。所有代码与对象一起装入。但是,脚本引擎尚未在脚本元素与对象事件之间建立连接。如果脚本运行到需要执行事件处理的地方,它就被阻塞(停止),直至脚本引擎完成所需的初始化。
Connected(已连接) 脚本引擎做好了去执行需要由它来执行的每项任务的准备时,就是进入了这种状态。
Disconnected(连接暂停) 脚本引擎进入这一状态后,实际上脚本已暂停。脚本仍处于装入状态,所有连接依然存在,但脚本引擎却不准备回答主机的请求。脚本引擎可以在不丢失脚本当前运行位置的情况下,离开这一状态并返回已连接状态。
Closed(关闭) 在这种状态中的脚本引擎,不再回答调用。你发出IActiveScript::Close()调用后,就进入这一状态。
上一篇: 设计Web页
下一篇: 属性页(一)