ActiveX Scripting技术(一)

   ActiveX Scripting技术是Microsoft ActiveX技术的一个组成部
分,它的主要目的是使应用程序在不被修改的情况下,为各种脚本语言
所控制。在软件交互性不断提高的今天,仅仅提供菜单或工具箱的界
面已经不能满足用户的需要了,软件的可定制特性已经成为当今软件
的一项基本特征,尤其对于一些通用的软件更为如此。大家比较熟悉
的Microso ft Office,比如Word字处理软件,它不仅提供了界面的任
意定制,还提供了方便的BASIC语言的可编程特性,用户可以通过编写B
ASIC语言实现较为复杂的功能扩充。
    Microsoft提供的ActiveX Scripting技术可使软件扩充变得非常
简单,软件开发商利用脚本引擎(Script Engine)支持脚本语言的解释
和执行操作,而软件用户可以根据需要编写自己的脚本代码,交由软件
处理。对于用户来说,就好像自己在编写程序控制应用程序,以完成自
己所期望的功能。而应用软件并不需要自己去解释执行用户的脚本代
码,只要利用脚本引擎就可以很方便地实现对用户脚本语言的支持。
应用系统也可以利用这种技术来提供二次开发的特性。
    虽然脚本引擎提供了脚本语言的解释执行的功能,但要用好Activ
eX Scripting技术则需要对它有一个全面的了解。本系列讲座将对Ac
tiveX Scripting技术作一探讨,并给出一个具体例子,以使读者进一
步理解ActiveX Scripting技术。
    一、ActiveX Scripting背景
    ActiveX Scripting是Microsoft的Automation技术和Script技术
结合的产物。因此,在介绍ActiveX Scripting之前,首先我们来看看A
utomation和Script两种技术的发展情况。
    1. Automation技术是Microsoft OLE技术的一部分,它可使解释
性的宏语言(主要是Visual Basic)能够在不了解应用程序的实现细节
的情况下控制Automation对象。随着V isual Basic软件的发展以及M
icrosoft Office套件的广泛应用,Automation技术已经成为连接这些
应用或者工具的纽带。而且,更多的应用把这种宏语言作为自己应用
扩展的手段,例如Word、Access以及Notes都把BASIC类语言作为其开
发语言,并且这些BASIC类语言均支持Automation对象;另一方面,Inte
rnet浏览器也提供了脚本引擎,可用于解释网络页面脚本语言中的Aut
omation对象。所有这些应用能够得以不断发展,在很大程度上是因为
这些BASIC语言或脚本语言提供了对Automation的支持。
    Automation技术以COM(组件对象模型)为基础,所有的Automation
对象都实现了标准的IDispatch接口,通过IDispatch接口暴露对象的
属性和方法,以便在客户程序中使用这些属性并调用它所支持的方法
。Automation对象的客户程序或者宿主程序通过类型库(T ypeLibrar
y)获得对象运行时刻的类型信息,并提供事件处理。宏语言解释器或
者脚本引擎根据对象的类型信息,把其中对对象属性和方法的引用解
释为对IDispatch接口成员函数Invoke的调用,从而实现对对象的控制

    2. Script技术是指脚本语言的技术,目前主要用于Internet浏览
器中,它可实现对页面的交互处理。我们知道,HTML是一种描述性的语
言,交互能力很弱,但通过Script技术, 可以编制出一些内容生动、具
有极强交互性的网络页面;并且使用Script技术的另一个好处是,它能
够减轻服务器端计算的负担,把部分计算工作转移到客户端来完成。
目前VBSc ript和JavaScript语言在网络浏览器上应用非常广泛,而且
一些主要的浏览器也提供了相应的引擎用于处理网页中的脚本语言。
    通常来说,用于网络浏览器的脚本语言具有以下特点:(1)它本身
是一门解释性语言, 所以语言的语法简单,但执行效率相对较低;(2)
它采用了事件驱动机制,脚本语言主要用于对交互事件作出响应,脚本
语言程序的主体是事件处理过程;(3)与浏览器内在的对象模型结构结
合紧密,脚本语言单独作为编程语言的价值很小,只有同特定的对象模
型结构相结合后才能够体现出其控制能力。在HTML的脚本程序中用户
可以直接使用如Window、Pa ne、Document等浏览器结构元素,并对其
进行控制,产生各种效果。此外脚本语言还可以对页面上的Java Appl
et和ActiveX Control进行操作。能够对宿主应用的对象进行控制正
是脚本语言的真正价值所在。
    从上面对两种技术的讨论中不难看出,Automation技术作为对应
用程序进行外部控制的成熟而有力的手段,其设计目标与Script技术
有许多共同之处。而Automation技术的基础COM技术本身是一种语言
无关的软件模型,一个很自然的想法是通过COM来统一实现对对象的控
制和对多种脚本语言的无缝支持。这种想法体现在实践上就形成了Mi
crosoft的A ctiveX Scripting技术。
    二、ActiveX Scripting结构
    从技术的角度来看,ActiveX Scripting技术实际上是一组COM接
口的定义,通过这组接口建立应用程序和脚本引擎之间的关系。脚本
引擎是ActiveX Scripting技术的实现, 一个应用系统如果实现了有
关的标准接口,那么它就可以通过脚本引擎提供对用户脚本语言的支
持。在介绍这组接口之前,我们先看看应用系统、脚本引擎和脚本文
件三者之间的关系。
    应用系统为了支持脚本语言,首先它要实现几个标准接口,然后它
把自己的一些被控对象暴露出来;脚本文件是一个文本文件,文件中包
含了一些程序代码;脚本引擎本身是一个COM对象,它负责对脚本文件
的解释和执行工作,在必要时通过应用系统的接口与其交互。三者的
关系如图1所示。
图1 应用系统、脚本引擎和脚本文件三者之间的关系
    在图1中,应用系统首先需要创建脚本引擎对象,并设置必要的参
数,然后装入脚本文件,再启动引擎,使引擎进入连接状态(即运行脚本
状态),通常我们通过用户显式操作(例如通过菜单命令或快捷键)完成
启动操作;应用系统也可以终止引擎的运行,使其进入无连接状态。在
引擎处于连接状态时,当特定的事件被激发时,脚本文件中的相应的事
件控制函数会被执行;在引擎处于无连接状态时,即使有事件发生,脚
本文件中的事件控制函数也不会被执行。
    应用系统也需要实现一些接口,分别为:IActiveScriptSite和IAc
tiveScriptSiteWi ndow(可选)。接口IActiveScriptSite是每一个支
持脚本语言的应用系统所必须实现的接口,脚本引擎通过它来获取其
宿主程序的信息,特别是在解释脚本语言中一些名字时更需要用到这
些信息,IActiveScriptSite的接口定义如下:
    class IActiveScriptSite : public IUnknown
    {
    public :
    virtual HRESULT GetLCID( LCID *plcid) = 0;
    virtual HRESULT GetItemInfo( LPCOLESTR pstrName, DWORD d
wReturnMask, IUn known *ppiunkItem, ITypeInfo *ppti) = 0;
    virtual HRESULT GetDocVersionString(BSTR *pbstrVersion)
= 0;
    virtual HRESULT OnScriptTerminate(const VARIANT *pvarRes
ult, const EXCEP INFO *pexcepinfo) = 0;
    virtual HRESULT OnStateChange( SCRIPTSTATE ssScriptState
) = 0;
    virtual HRESULT OnScriptError( IActiveScriptError *pscri
pterror) = 0;
    virtual HRESULT OnEnterScript( void) = 0;
    virtual HRESULT OnLeaveScript( void) = 0;
    };
    在这些成员函数中,GetItemInfo是关键函数,因为脚本引擎管理
了一个名字空间,脚本引擎在解释执行过程中,如果需要某个名字的信
息,则通过宿主程序的IActiveScriptS ite::GetItemInfo函数获取。
所以,应用系统通过GetItemInfo成员函数把自己的一些对象暴露给脚
本引擎,以便在脚本文件中引用。
    IActiveScriptSiteWindow接口是一个可选的接口,如果在脚本文
件中要用到用户接口UI特性,则应用系统应该实现IActiveScriptSite
Window接口,其定义很简单,如下:
    class IActiveScriptSiteWindow : public IUnknown
    {
    public :
    virtual HRESULT GetWindow( HWND *phwnd ) = 0;
    virtual HRESULT EnableModeless( BOOL fEnable ) = 0;
    };
    脚本引擎通过GetWindow成员函数获取宿主窗口句柄,作为脚本中
弹出窗口的父窗口。
    除了应用系统需要实现上面两个接口用作它与脚本引擎之间的通
讯之外,脚本引擎也实现了一组接口用作两者之间的通讯,这组接口包
括:IActiveScript、IActiveScriptPa rse和其它一些用于调试、状
态管理或者错误处理的接口,IActiveScript和IActiveScri ptParse
是必须实现的接口,以下是它们的定义:
    class IActiveScript : public IUnknown
    {
    public:
    virtual HRESULT SetScriptSite( IActiveScriptSite *pass)
= 0;
    virtual HRESULT GetScriptSite( REFIID riid, void **ppvOb
ject) = 0;
    virtual HRESULT SetScriptState( SCRIPTSTATE ss) = 0;
    virtual HRESULT GetScriptState( SCRIPTSTATE *pssState) =
0;
    virtual HRESULT Close( void) = 0;
    virtual HRESULT AddNamedItem( LPCOLESTR pstrName, DWORD
dwFlags) = 0;
    virtual HRESULT AddTypeLib( REFGUID rguidTypeLib, DWORD
dwMajor, DWORD d wMinor, DWORD dwFlags) = 0;
    virtual HRESULT GetScriptDispatch( LPCOLESTR pstrItemNam
e, IDispatch**pp disp) = 0;
    virtual HRESULT GetCurrentScriptThreadID( SCRIPTTHREADID
*pstidThread) = 0;
    virtual HRESULT GetScriptThreadID( DWORD dwWin32ThreadId
,SCRIPTTHREADID* pstidThread) = 0;
    virtual HRESULT GetScriptThreadState( SCRIPTTHREADID sti
dThread, SCRIPTT HREADSTATE *pstsState) = 0;
    virtual HRESULT InterruptScriptThread( SCRIPTTHREADID st
idThread,const E XCEPINFO *pexcepinfo, DWORD dwFlags) = 0;
    virtual HRESULT Clone( IActiveScript **ppscript) = 0;
    };
    class IActiveScriptParse : public IUnknown
    {
    public:
    virtual HRESULT InitNew( void) = 0;
    virtual HRESULT AddScriptlet( LPCOLESTR pstrDefaultName,
LPCOLESTR pstrCo de,LPCOLESTR pstrItemName, LPCOLESTR pstrSu
bItemName, LPCOLESTR pstrEventNam e, LPCOLESTR pstrDelimiter
, DWORD dwSourceContextCookie, ULONG ulStartingLin eNumber,
DWORD dwFlags, BSTR *pbstrName, EXCEPINFO *pexcepinfo) = 0;
    virtual HRESULT ParseScriptText( LPCOLESTR pstrCode, LPC
OLESTR pstrItemN ame,IUnknown *punkContext, LPCOLESTR pstrDe
limiter,DWORD dwSourceContextCook ie, ULONG ulStartingLineNu
mber,DWORD dwFlags, VARIANT *pvarResult,EXCEPINFO *pexcepinf
o) = 0;
    };
    应用系统通过IActiveScript接口控制脚本引擎的各种行为,也可
以获取引擎的各种状态。通常,应用系统首先调用IActiveScript::Se
tScriptSite成员函数把自身实现的I ActiveScriptSite接口传递给
引擎,以后引擎就通过该接口与应用系统通讯。而应用系统也可以通
过IActiveScript的其它成员函数获取或者设置引擎的运行状态。接
口IActive ScriptParse用于对脚本代码的操作,应用系统利用IActiv
eScriptParse接口装入脚本代码。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值