ActiveX Scripting技术(一)

    技术2026-06-05  6

       ActiveX Scripting技术是Microsoft ActiveX技术的一个组成部分,它的主要目的是使应用程序在不被修改的情况下,为各种脚本语言所控制。在软件交互性不断提高的今天,仅仅提供菜单或工具箱的界面已经不能满足用户的需要了,软件的可定制特性已经成为当今软件的一项基本特征,尤其对于一些通用的软件更为如此。大家比较熟悉的Microso ft Office,比如Word字处理软件,它不仅提供了界面的任意定制,还提供了方便的BASIC语言的可编程特性,用户可以通过编写BASIC语言实现较为复杂的功能扩充。    Microsoft提供的ActiveX Scripting技术可使软件扩充变得非常简单,软件开发商利用脚本引擎(Script Engine)支持脚本语言的解释和执行操作,而软件用户可以根据需要编写自己的脚本代码,交由软件处理。对于用户来说,就好像自己在编写程序控制应用程序,以完成自己所期望的功能。而应用软件并不需要自己去解释执行用户的脚本代码,只要利用脚本引擎就可以很方便地实现对用户脚本语言的支持。应用系统也可以利用这种技术来提供二次开发的特性。    虽然脚本引擎提供了脚本语言的解释执行的功能,但要用好ActiveX Scripting技术则需要对它有一个全面的了解。本系列讲座将对ActiveX Scripting技术作一探讨,并给出一个具体例子,以使读者进一步理解ActiveX Scripting技术。    一、ActiveX Scripting背景    ActiveX Scripting是Microsoft的Automation技术和Script技术结合的产物。因此,在介绍ActiveX Scripting之前,首先我们来看看Automation和Script两种技术的发展情况。    1. Automation技术是Microsoft OLE技术的一部分,它可使解释性的宏语言(主要是Visual Basic)能够在不了解应用程序的实现细节的情况下控制Automation对象。随着V isual Basic软件的发展以及Microsoft Office套件的广泛应用,Automation技术已经成为连接这些应用或者工具的纽带。而且,更多的应用把这种宏语言作为自己应用扩展的手段,例如Word、Access以及Notes都把BASIC类语言作为其开发语言,并且这些BASIC类语言均支持Automation对象;另一方面,Internet浏览器也提供了脚本引擎,可用于解释网络页面脚本语言中的Automation对象。所有这些应用能够得以不断发展,在很大程度上是因为这些BASIC语言或脚本语言提供了对Automation的支持。    Automation技术以COM(组件对象模型)为基础,所有的Automation对象都实现了标准的IDispatch接口,通过IDispatch接口暴露对象的属性和方法,以便在客户程序中使用这些属性并调用它所支持的方法。Automation对象的客户程序或者宿主程序通过类型库(T ypeLibrary)获得对象运行时刻的类型信息,并提供事件处理。宏语言解释器或者脚本引擎根据对象的类型信息,把其中对对象属性和方法的引用解释为对IDispatch接口成员函数Invoke的调用,从而实现对对象的控制。    2. Script技术是指脚本语言的技术,目前主要用于Internet浏览器中,它可实现对页面的交互处理。我们知道,HTML是一种描述性的语言,交互能力很弱,但通过Script技术, 可以编制出一些内容生动、具有极强交互性的网络页面;并且使用Script技术的另一个好处是,它能够减轻服务器端计算的负担,把部分计算工作转移到客户端来完成。目前VBSc ript和JavaScript语言在网络浏览器上应用非常广泛,而且一些主要的浏览器也提供了相应的引擎用于处理网页中的脚本语言。    通常来说,用于网络浏览器的脚本语言具有以下特点:(1)它本身是一门解释性语言, 所以语言的语法简单,但执行效率相对较低;(2)它采用了事件驱动机制,脚本语言主要用于对交互事件作出响应,脚本语言程序的主体是事件处理过程;(3)与浏览器内在的对象模型结构结合紧密,脚本语言单独作为编程语言的价值很小,只有同特定的对象模型结构相结合后才能够体现出其控制能力。在HTML的脚本程序中用户可以直接使用如Window、Pa ne、Document等浏览器结构元素,并对其进行控制,产生各种效果。此外脚本语言还可以对页面上的Java Applet和ActiveX Control进行操作。能够对宿主应用的对象进行控制正是脚本语言的真正价值所在。    从上面对两种技术的讨论中不难看出,Automation技术作为对应用程序进行外部控制的成熟而有力的手段,其设计目标与Script技术有许多共同之处。而Automation技术的基础COM技术本身是一种语言无关的软件模型,一个很自然的想法是通过COM来统一实现对对象的控制和对多种脚本语言的无缝支持。这种想法体现在实践上就形成了Microsoft的A ctiveX Scripting技术。    二、ActiveX Scripting结构    从技术的角度来看,ActiveX Scripting技术实际上是一组COM接口的定义,通过这组接口建立应用程序和脚本引擎之间的关系。脚本引擎是ActiveX Scripting技术的实现, 一个应用系统如果实现了有关的标准接口,那么它就可以通过脚本引擎提供对用户脚本语言的支持。在介绍这组接口之前,我们先看看应用系统、脚本引擎和脚本文件三者之间的关系。    应用系统为了支持脚本语言,首先它要实现几个标准接口,然后它把自己的一些被控对象暴露出来;脚本文件是一个文本文件,文件中包含了一些程序代码;脚本引擎本身是一个COM对象,它负责对脚本文件的解释和执行工作,在必要时通过应用系统的接口与其交互。三者的关系如图1所示。图1 应用系统、脚本引擎和脚本文件三者之间的关系    在图1中,应用系统首先需要创建脚本引擎对象,并设置必要的参数,然后装入脚本文件,再启动引擎,使引擎进入连接状态(即运行脚本状态),通常我们通过用户显式操作(例如通过菜单命令或快捷键)完成启动操作;应用系统也可以终止引擎的运行,使其进入无连接状态。在引擎处于连接状态时,当特定的事件被激发时,脚本文件中的相应的事件控制函数会被执行;在引擎处于无连接状态时,即使有事件发生,脚本文件中的事件控制函数也不会被执行。    应用系统也需要实现一些接口,分别为:IActiveScriptSite和IActiveScriptSiteWi ndow(可选)。接口IActiveScriptSite是每一个支持脚本语言的应用系统所必须实现的接口,脚本引擎通过它来获取其宿主程序的信息,特别是在解释脚本语言中一些名字时更需要用到这些信息,IActiveScriptSite的接口定义如下:    class IActiveScriptSite : public IUnknown    {    public :    virtual HRESULT GetLCID( LCID *plcid) = 0;    virtual HRESULT GetItemInfo( LPCOLESTR pstrName, DWORD dwReturnMask, IUn known *ppiunkItem, ITypeInfo *ppti) = 0;    virtual HRESULT GetDocVersionString(BSTR *pbstrVersion) = 0;    virtual HRESULT OnScriptTerminate(const VARIANT *pvarResult, const EXCEP INFO *pexcepinfo) = 0;    virtual HRESULT OnStateChange( SCRIPTSTATE ssScriptState) = 0;    virtual HRESULT OnScriptError( IActiveScriptError *pscripterror) = 0;    virtual HRESULT OnEnterScript( void) = 0;    virtual HRESULT OnLeaveScript( void) = 0;    };    在这些成员函数中,GetItemInfo是关键函数,因为脚本引擎管理了一个名字空间,脚本引擎在解释执行过程中,如果需要某个名字的信息,则通过宿主程序的IActiveScriptS ite::GetItemInfo函数获取。所以,应用系统通过GetItemInfo成员函数把自己的一些对象暴露给脚本引擎,以便在脚本文件中引用。    IActiveScriptSiteWindow接口是一个可选的接口,如果在脚本文件中要用到用户接口UI特性,则应用系统应该实现IActiveScriptSiteWindow接口,其定义很简单,如下:    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 **ppvObject) = 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 pstrItemName, IDispatch**pp disp) = 0;    virtual HRESULT GetCurrentScriptThreadID( SCRIPTTHREADID*pstidThread) = 0;    virtual HRESULT GetScriptThreadID( DWORD dwWin32ThreadId,SCRIPTTHREADID* pstidThread) = 0;    virtual HRESULT GetScriptThreadState( SCRIPTTHREADID stidThread, SCRIPTT HREADSTATE *pstsState) = 0;    virtual HRESULT InterruptScriptThread( SCRIPTTHREADID stidThread,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 pstrSubItemName, LPCOLESTR pstrEventNam e, LPCOLESTR pstrDelimiter, DWORD dwSourceContextCookie, ULONG ulStartingLin eNumber, DWORD dwFlags, BSTR *pbstrName, EXCEPINFO *pexcepinfo) = 0;    virtual HRESULT ParseScriptText( LPCOLESTR pstrCode, LPCOLESTR pstrItemN ame,IUnknown *punkContext, LPCOLESTR pstrDelimiter,DWORD dwSourceContextCook ie, ULONG ulStartingLineNumber,DWORD dwFlags, VARIANT *pvarResult,EXCEPINFO *pexcepinfo) = 0;    };    应用系统通过IActiveScript接口控制脚本引擎的各种行为,也可以获取引擎的各种状态。通常,应用系统首先调用IActiveScript::SetScriptSite成员函数把自身实现的I ActiveScriptSite接口传递给引擎,以后引擎就通过该接口与应用系统通讯。而应用系统也可以通过IActiveScript的其它成员函数获取或者设置引擎的运行状态。接口IActive ScriptParse用于对脚本代码的操作,应用系统利用IActiveScriptParse接口装入脚本代码。

    最新回复(0)