




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、ActiveX Scripting技术介绍吕思伟 潘爱民北京大学计算机科学技术研究所【摘要】本文首先介绍了ActiveX Scripting技术的背景,然后讲述了ActiveX Scripting技术的结构和实现,并通过实例说明了如何为一个应用程序加上脚本特性的过程。关键字:ActiveX Scripting、Automation、OLE、COMActiveX Scripting技术是Microsoft 的ActiveX技术的一个组成部分,它主要目的是使应用程序在不被修改的情况下,为各种脚本语言所控制。在软件交互性不断提高的今天,仅仅提供菜单或工具箱的界面已经不能满足用户的需要了,软件的可定制
2、特性已经成为当今软件的一项基本特征,尤其对于一些通用的软件更为如此。大家比较熟悉的Microsoft Office软件,比如Word字处理软件,它不仅提供了界面的任意定制,还提供了方便的Basic语言的可编程特性,用户可以通过编写BASIC语言实现较为复杂的功能扩充。Micosoft提供的ActiveX Scripting技术可使软件扩充变得非常简单,软件开发商利用脚本引擎(Script Engine)支持脚本语言的解释和执行操作,而软件用户可以根据需要编写自己的脚本代码,交由软件处理,对于用户来说,就好象自己在编写程序控制应用程序,以完成自己所期望的功能。而应用软件并不需要自己去解释执行用户
3、的脚本代码,只要利用脚本引擎就可以很方便地实现对用户脚本语言的支持。应用系统也可以利用这种技术来提供二次开发的特性。虽然脚本引擎提供了脚本语言的解释执行的功能,但要用好ActiveX Scripting技术则需要对它有一个全面的了解,本文将对ActiveX Scripting技术作一探讨,并给出一个具体例子,以使读者进一步理解ActiveX Scripting技术。一、ActiveX Scripting背景ActiveX Scripting是Microsoft 的Automation技术和Script技术结合的产物,因此,在介绍ActiveX Scripting之前,首先我们来看看Automa
4、tion和Script两种技术的发展情况。(1) Automation技术是Microsoft OLE技术 的一部分,它可使解释性的宏语言(主要是Visual Basic)能够在不了解应用程序的实现细节的情况下控制Automation对象,随着Visual Basic软件的发展以及Microsoft Office套件的广泛应用,Automation技术已经成为连接这些应用或者工具的纽带。而且,更多的应用把这种宏语言作为自己应用扩展的手段,例如Word、Access以及Notes都把BASIC类语言作为其开发语言,并且这些BASIC类语言均支持Automati
5、on对象;另一方面,Internet浏览器也提供了脚本引擎,可用于解释网络页面脚本语言中的Automation对象。所有这些应用能够得以不断发展,在很大程度上是因为这些BASIC语言或脚本语言提供了对Automation的支持。Automation技术以COM(组件对象模型)为基础,所有的Automation对象都实现了标准的IDispatch接口,通过IDispatch接口暴露对象的属性和方法,以便在客户程序中使用这些属性并调用它所支持的方法。Automation对象的客户程序或者宿主程序通过类型库(Type Library)获得对象运行时刻的类型信息,并提供事件处理。宏语言解释器或者脚本引
6、擎根据对象的类型信息,把其中对对象属性和方法的引用解释为对IDispatch接口成员函数Invoke的调用,从而实现对对象的控制。(2) Script技术是指脚本语言的技术,目前主要用于Internet浏览器中,它可实现对页面的交互处理。我们知道,HTML是一种描述性的语言,交互能力很弱,但通过Script技术,可以编制出一些内容生动、具有极强交互性的网络页面;并且,使用Script技术的另一个好处是,它能够减轻服务器端计算的负担,把部分计算工作转移到客户端来完成。目前VBScript和JavaScript语言在网络浏览器上应用非常广泛,而且一些主要的浏览器
7、也提供了相应的引擎用于处理网页中的脚本语言。通常来说,用于网络浏览器的脚本语言具有以下特点:(1) 它本身是一门解释性语言,所以语言的语法简单,但执行效率相对较低;(2) 它采用了事件驱动机制,脚本语言主要用于对交互事件作出响应,脚本语言程序的主体是事件处理过程;(3) 与浏览器内在的对象模型结构结合紧密,脚本语言单独作为编程语言的价值很小,只有同特定的对象模型结构相结合后才能够体现出其控制能力。在HTML的脚本程序中用户可以直接使用如Window、Pane、Document等浏览器结构元素,并对其进行控制,产生各种效果。此外脚本语言还可以对页面上的Java Applet和ActiveX Co
8、ntrol进行操作。能够对宿主应用的对象进行控制正是脚本语言的真正价值所在。从上面对两种技术的讨论中不难看出,Automation技术作为对应用程序进行外部控制的成熟而有力的手段,其设计目标与Script技术有许多共同之处。而Automation技术的基础COM技术本身是一种语言无关的软件模型,一个很自然的想法是通过COM来统一实现对对象的控制和对多种脚本语言的无缝支持。这种想法体现在实践上就形成了Microsoft的Active Scripting技术。二、ActiveX Scripting结构从技术的角度来看,ActiveX Scripting技术实际上是一组COM接口的定义,通过这组接口
9、建立应用程序和脚本引擎之间的关系。脚本引擎是ActiveX Scripting技术的实现,一个应用系统如果实现了有关的标准接口,那么它就可以通过脚本引擎提供对用户脚本语言的支持,在介绍这组接口之前,我们先看看应用系统、脚本引擎和脚本文件三者之间的关系。应用系统为了支持脚本语言,首先它要实现几个标准接口,然后它把自己的一些被控对象暴露出来;脚本文件是一个文本文件,文件中包含了一些程序代码;脚本引擎本身是一个COM对象,它负责对脚本文件的解释和执行工作,在必要时通过应用系统的接口与其交互。三者的关系如图1所示:图 1 应用系统、脚本引擎和脚本文件三者之间的关系在图1中,应用系统首先需要创建脚本引擎
10、对象,并设置必要的参数,然后装入脚本文件,再启动引擎,使引擎进入连接状态(即运行脚本状态),通常我们通过用户显式操作(例如通过菜单命令或快捷键)完成启动操作;应用系统也可以终止引擎的运行,使其进入无连接状态。在引擎处于连接状态时,当特定的事件被激发时,脚本文件中的相应的事件控制函数会被执行;在引擎处于无连接状态时,即使有事件发生,脚本文件中的事件控制函数也不会被执行。应用系统也需要实现一些接口,分别为:IActiveScriptSite和IActiveScriptSiteWindow(可选)。接口IActiveScriptSite是每一个支持脚本语言的应用系统所必须实现的接口,脚本引擎通过它来
11、获取其宿主程序的信息,特别是在解释脚本语言中一些名字时更需要用到这些信息,IActiveScriptSite的接口定义如下:class IActiveScriptSite : public IUnknownpublic : virtual HRESULT GetLCID( LCID *plcid) = 0; virtual HRESULT GetItemInfo( LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown *ppiunkItem, ITypeInfo *ppti) = 0; virtual HRESULT GetDocVersionStr
12、ing(BSTR *pbstrVersion) = 0; virtual HRESULT OnScriptTerminate(const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo) = 0; virtual HRESULT OnStateChange( SCRIPTSTATE ssScriptState) = 0; virtual HRESULT OnScriptError( IActiveScriptError *pscripterror) = 0; virtual HRESULT OnEnterScript( void) = 0; v
13、irtual HRESULT OnLeaveScript( void) = 0;返回 下一页>>>在这些成员函数中,GetItemInfo是关键函数,因为脚本引擎管理了一个名字空间,脚本引擎在解释执行过程中,如果需要某个名字的信息,则通过宿主程序的IActiveScriptSite:GetItemInfo函数获取。所以,应用系统通过GetItemInfo成员函数把自己的一些对象暴露给脚本引擎,以便在脚本文件中引用。IActiveScriptSiteWindow接口是一个可选的接口,如果在脚本文件中要用到用户接口UI特性,则应用系统应该实现IActiveS
14、criptSiteWindow接口,其定义很简单,如下:class IActiveScriptSiteWindow : public IUnknownpublic : virtual HRESULT GetWindow( HWND *phwnd ) = 0; virtual HRESULT EnableModeless( BOOL fEnable ) = 0;脚本引擎通过GetWindow成员函数获取宿主窗口句柄,作为脚本中弹出窗口的父窗口。除了应用系统需要实现上面两个接口用作它与脚本引擎之间的通讯之外,脚本引擎也实现了一组接口用作两者之间的通讯,这组接口包括:IActiveScript、IA
15、ctiveScriptParse和其它一些用于调试、状态管理或者错误处理的接口,IActiveScript和IActiveScriptParse是必须实现的接口,以下是它们的定义:class IActiveScript : public IUnknownpublic:virtual HRESULT SetScriptSite( IActiveScriptSite *pass) = 0;virtual HRESULT GetScriptSite( REFIID riid, void *ppvObject) = 0;virtual HRESULT SetScriptState( SCRIPTSTA
16、TE 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 dwMinor, DWORD dwFlags) = 0;virtual HRESULT GetScriptDisp
17、atch( LPCOLESTR pstrItemName, IDispatch *ppdisp) = 0;virtual HRESULT GetCurrentScriptThreadID( SCRIPTTHREADID *pstidThread) = 0;virtual HRESULT GetScriptThreadID( DWORD dwWin32ThreadId, SCRIPTTHREADID *pstidThread) = 0;virtual HRESULT GetScriptThreadState( SCRIPTTHREADID stidThread, SCRIPTTHREADSTAT
18、E *pstsState) = 0;virtual HRESULT InterruptScriptThread( SCRIPTTHREADID stidThread, const EXCEPINFO *pexcepinfo, DWORD dwFlags) = 0;virtual HRESULT Clone( IActiveScript *ppscript) = 0;class IActiveScriptParse : public IUnknownpublic:virtual HRESULT InitNew( void) = 0;virtual HRESULT AddScriptlet( LP
19、COLESTR pstrDefaultName,LPCOLESTR pstrCode, LPCOLESTR pstrItemName,LPCOLESTR pstrSubItemName, LPCOLESTR pstrEventName,LPCOLESTR pstrDelimiter, DWORD dwSourceContextCookie,ULONG ulStartingLineNumber, DWORD dwFlags,BSTR *pbstrName, EXCEPINFO *pexcepinfo) = 0;virtual HRESULT ParseScriptText( LPCOLESTR
20、pstrCode, LPCOLESTR pstrItemName,IUnknown *punkContext, LPCOLESTR pstrDelimiter,DWORD dwSourceContextCookie, ULONG ulStartingLineNumber,DWORD dwFlags, VARIANT *pvarResult,EXCEPINFO *pexcepinfo) = 0;应用系统通过IActiveScript接口控制脚本引擎的各种行为,也可以获取引擎的各种状态。通常,应用系统首先调用IActiveScript:SetScriptSite成员函数把自身实现的IActiveS
21、criptSite接口传递给引擎,以后引擎就通过该接口与应用系统通讯。而应用系统也可以通过IActiveScript的其它成员函数获取或者设置引擎的运行状态。接口IActiveScriptParse用于对脚本代码的操作,应用系统利用IActiveScriptParse接口装入脚本代码。在介绍了应用系统和脚本引擎所实现的一些关键接口之后,我们再进一步看看应用系统和脚本引擎的协作过程,如图2所示:图 2 应用系统与脚本引擎的协作过程图中给出了8个步骤,下面逐一介绍:(1) 创建必要的受控对象,这些受控对象是指将要在脚本文件中引用到的Automation对象,通常
22、是应用系统的文档对象,也可以是某些ActiveX控制;(2) 创建引擎对象,不同的脚本语言使用不同的引擎对象,通常我们使用VBScript引擎或者JavaScript引擎,创建得到的接口指针是应用系统控制引擎的唯一途径;(3) 装入脚本文件,调用引擎的IActiveScriptParse接口的ParseScriptText成员函数把脚本代码装入到引擎中,注意ParseScriptText成员函数只接收UNICODE字符串,如果程序中用到了ANSI字符串,则需要进行转换才能装入到引擎中;(4)
23、0; 加入名字项,凡是应用系统中要暴露给脚本文件的所有对象都需要加入到引擎的名字空间中,可以通过调用IActiveScript接口的AddNamedItem成员函数来完成;(5) 启动引擎,以便运行脚本,直接调用IActiveScript:SetScriptState成员函数使其进入连接状态(运行状态)即可;(6) 引擎在执行脚本时,首先处理其名字空间中的名字项,调用应用系统IActiveScriptSite接口的GetItemInfo成员函数获取每一个名字所对应的受控对象的信息,主要是COM接口;如果在脚本中有事件控制函
24、数的话,则还要获取受控对象的类型信息;(7) 在脚本执行过程中,当特定的事件发生时,引擎中的事件控制函数就要被调用;(8) 在脚本执行过程中,有可能会调用到受控对象的属性和方法,则引擎会通过它所获取的对象接口调用IDispatch:Invoke成员函数;(9) 如果应用系统希望终止引擎的执行过程,可以调用IActiveScript:SetScriptState成员函数使其进入非运行状态即可。以上的步骤基本上反映了应用系统和引擎之间的协作过程。在实际使用过程中,可以根据情况的不同灵活应用。
25、三、ActiveX Scripting实现因为Microsoft或者其它的软件厂商已经为我们提供了脚本引擎(如果机器上安装了Internet Explorer,则VBScript和JavaScript的引擎就已经被安装在机器上了),所以我们只需要在应用系统中直接使用就可以。为了使应用系统更好地支持这种脚本特性,我们对实现脚本特性过程中的一些要点作一分析。首先我们定义一个通用的类CScriptHost,它实现了两个接口IActiveScriptSite和IActiveScriptSiteWindow,类的定义如下:class CScriptHost : public IActiveScriptS
26、ite , public IActiveScriptSiteWindowpublic:CScriptHost(LPUNKNOWN lpUnkCtrl, LPCOLESTR pNamedItem, HWND hWnd);virtual CScriptHost();HRESULT CreateScriptEngine();HRESULT ParseFile(const char* pszFileName,LPCOLESTR pstrItemName);public:/IUnknown membersSTDMETHOD(QueryInterface)(REFIID riid,void* ppvObj
27、);STDMETHOD_(unsigned long,AddRef)(void);STDMETHOD_(unsigned long,Release)();/IActiveScriptSite membersSTDMETHOD(GetLCID)(LCID *plcid) ;STDMETHOD(GetItemInfo)(LPCOLESTR pstrName,DWORD dwReturnMask,IUnknown * *ppiunkItem,ITypeInfo * *ppti) ;STDMETHOD(GetDocVersionString)(BSTR *pbstrVersion) ;STDMETHO
28、D(OnScriptTerminate)(const VARIANT *pvarResult,const EXCEPINFO *pexcepinfo) ;STDMETHOD(OnStateChange)(SCRIPTSTATE ssScriptState) ;STDMETHOD(OnScriptError)(IActiveScriptError *pscripterror) ;STDMETHOD(OnEnterScript)(void) ;STDMETHOD(OnLeaveScript)(void) ;/IActiveScriptSiteWindow membersSTDMETHOD(GetW
29、indow)(HWND *phwnd) ;STDMETHOD(EnableModeless)(BOOL fEnable);public:IActiveScript* m_ps;IActiveScriptParse* m_psp;private:UINT m_cref;CLSID m_clsidEngine;LPUNKNOWN m_lpUnkCtrl;LPOLESTR m_pNamedItem;HWND m_Wnd;类CScriptHost通过多继承的方法实现了两个接口,并负责脚本引擎的创建和维护工作。其数据成员m_ps和m_psp用于保存引擎的IActiveScript和IActiveScri
30、ptParse接口指针;数据成员m_clsidEngine记录了引擎的类ID;m_Wnd记录了应用系统提供给引擎的主窗口;m_lpUnkCtrl记录了应用系统的唯一的一个受控对象,m_pNamedItem记录了受控对象的名字。在CScriptHost类的构造函数中初始设置m_lpUnkCtrl、m_pNamedItem和m_Wnd成员变量。构造函数和析构函数代码如下:CScriptHost:CScriptHost(LPUNKNOWN lpUnkCtrl, LPCOLESTR pNamedItem , HWND hWnd) : m_ps(NULL),m_psp(NULL),m_cref(0)m_
31、lpUnkCtrl = lpUnkCtrl;m_pNamedItem = pNamedItem;m_Wnd = hWnd; / the clsid of VBScript Enginestatic CLSID const clsid = 0xb54f3741, 0x5b07, 0x11cf, 0xa4, 0xb0, 0x0, 0xaa, 0x0, 0x4a, 0x55, 0xe8;/ Default to VBScriptm_clsidEngine = clsid;CScriptHost:CScriptHost()if(m_psp)m_psp->Release();/ we must f
32、irst close the script engineif(m_ps)m_ps->Close();m_ps->Release();在构造函数中,我们指定使用确省的VBScript脚本引擎对象,并设置其相应的CLSID。在析构函数中我们不能释放所有引擎的接口指针,因为这会导致脚本引擎对象释放这个指针时出错。在析构函数中调用IActiveScript:Close关闭与脚本引擎的连接。成员函数CreateScriptEngine是由应用系统调用的函数,代码如下:HRESULT CScriptHost:CreateScriptEngine()HRESULT hr = S_OK; hr =
33、 :CoCreateInstance(m_clsidEngine, NULL, CLSCTX_INPROC_SERVER, IID_IActiveScript,(void*)&m_ps);if ( SUCCEEDED( hr ) )/ QI the IActiveScriptParse pointerhr = m_ps->QueryInterface(IID_IActiveScriptParse, (void*)&m_psp);if (FAILED(hr) )m_ps->Release();return hr;/ set the script sitehr = m_
34、ps->SetScriptSite(this);if ( FAILED( hr ) )return hr;m_ps->SetScriptState(SCRIPTSTATE_INITIALIZED);/ initiate the script enginehr = m_psp->InitNew();if ( FAILED( hr ) )return hr;hr = m_ps->AddNamedItem(m_pNamedItem,SCRIPTITEM_ISVISIBLE | SCRIPTITEM_ISSOURCE); return hr;CreateScriptEngine
35、函数首先创建引擎对象,然后把引擎对象的IActiveScript和IActiveScriptParse接口指针分别赋给数据成员m_ps和m_psp,最后把m_pNamedItem名字加入到引擎的名字空间中。成员函数ParseFile可以把脚本文件装入到引擎中,代码如下:HRESULT CScriptHost:ParseFile(const char * pszFileName, LPCOLESTR pstrItemName) HRESULT hr = S_OK; struct _stat stat; size_t cch; EXCEPINFO ei; FILE *pfile; if(_stat
36、(pszFileName,&stat) return E_FAIL; cch = stat.st_size; char* pszAlloc = new charcch + 1; pszAlloccch = '0'/ this is vitally important if(pszAlloc = NULL) return E_OUTOFMEMORY; memset(pszAlloc,0,cch); / get the script text into a memory block pfile = fopen(pszFileName,"rb"); if
37、( !pfile ) hr = E_FAIL; return hr; fread(pszAlloc,cch,1,pfile); fclose(pfile); LPOLESTR pwszCode; int CharCount = MultiByteToWideChar(CP_ACP,0,pszAlloc,-1,NULL,0); pwszCode = new WCHARCharCount; MultiByteToWideChar(CP_ACP,0,pszAlloc,-1,pwszCode,CharCount); size_t t = wcslen(pwszCode); hr = m_psp->
38、;ParseScriptText(pwszCode, pstrItemName,NULL, NULL, 0,0,0L,NULL,&ei); delete pwszCode; delete pszAlloc; return hr;ParseFile函数首先确定脚本文件的长度,然后打开文件并装入到内存中,最后把内存中脚本代码通过引擎的IActiveScriptParse接口成员函数ParseScriptText成员函数装入到引擎中,需要注意的是,我们这里调用MuitiByteToWide函数完成了代码从ANSI 到UNICODE码的转换。然后我们看看类CScriptHost中接口IActi
39、veScriptSite的成员函数GetItemInfo的实现,因为引擎调用GetItemInfo函数获取其名字空间中名字项的信息,所以我们要在此函数中把应用系统的对象暴露给引擎和脚本,代码如下:STDMETHODIMP CScriptHost:GetItemInfo(LPCOLESTR pstrName,DWORD dwReturnMask,IUnknown *ppiunkItem, ITypeInfo *ppti) HRESULT hr = S_OK;/ initialize the sent-in pointersif(dwReturnMask & SCRIPTINFO_ITYP
40、EINFO)if(ppti = NULL)return E_INVALIDARG;*ppti = NULL;if(dwReturnMask & SCRIPTINFO_IUNKNOWN) if(ppiunkItem = NULL)return E_INVALIDARG;*ppiunkItem = NULL;if(!_wcsicmp(m_pNamedItem, pstrName)if(dwReturnMask & SCRIPTINFO_IUNKNOWN)/ give out the object's IUnknown pointer*ppiunkItem = m_lpUnk
41、Ctrl;static_cast<IUnknown*>(*ppiunkItem)->AddRef(); if(dwReturnMask & SCRIPTINFO_ITYPEINFO)IProvideClassInfo* pClsInfo = NULL;hr = m_lpUnkCtrl->QueryInterface(IID_IProvideClassInfo, (void*)&pClsInfo);if(pClsInfo != NULL)hr = pClsInfo->GetClassInfo(ppti);pClsInfo->Release();
42、return hr;函数GetItemInfo首先对输出参数ppiunkItem和ppti进行有效性检查,然后判断是否输入的名字与应用支持的受控对象的名字一致,如果一致的话,则根据参数dwReturnMask所指示的标志,把对象的IUnknown接口或者对象的类型信息通过输出参数传递给引擎,供引擎解释执行脚本代码使用。我们再看类CScriptHost中接口IActiveScriptSiteWindow的成员函数GetWindow的实现。函数比较简单,只是把应用系统的窗口句柄通过输出参数传递给引擎,代码如下:HRESULT CScriptHost:GetWindow(HWND *phwnd)if
43、 (m_Wnd != NULL) *phwnd = m_Wnd;return S_OK; else return E_FAIL;类CScriptHost的其它成员函数都比较简单,有的接口成员函数可以不实现,仅仅返回S_OK或者E_NOTIMPL即可,其代码不再一一列举。CScriptHost提供了应用系统为支持脚本代码运行所做的基本工作,CScriptHost为引擎提供了应用系统的必要信息。CScriptHost类是一个通用的类,如果应用系统只有一个Automation对象暴露给脚本代码,则可以用CScriptHost类快速实现对脚本代码的支持。如果应用系统有多个Automation对象要暴露
44、给脚本代码,则需要对上面介绍的CScriptHost类作些修改,使其支持多个名字项的处理。四、ActiveX Scripting实例在这一节,我们通过一个实例来说明如何利用上节提供的CScriptHost类为应用程序加上脚本特性。例程序很简单,只是一个基于对话框的应用,但对话框中有一个日历控制,这是Microsoft提供的ActiveX控制,它本身也是一个Automation对象,我们将在脚本代码中对该日历对象进行控制,并且在脚本代码中响应日历控制的一些事件。图3是例程序的运行界面图。图 3 例程序运行界面图创建例程序的过程并不复杂,利用Microsoft Visual C+ 5.0(或6.0
45、)提供的AppWizard和ClassWizard可以很快创建工程,并添加各项功能,下面是其操作过程:(1) 首先我们创建一个MFC工程,因为例程序比较简单,所以我们选择了基于对话框的应用类型。工程名为Script,对话框类名为CScriptDlg。(2) 然后我们在对话框资源模板中添加日历控制,打开对话框模板,用右键单击,从菜单中选择“Insert ActiveX Control”命令,选择Calendar Control,然后调整大小合适即可,并设置控制的ID为IDC_CONTROL1。(3) 在对话框模板中添加两个按钮“Load Script”和“Run Script”放在适当的位置上。
46、(4) 把上一节完成的文件ScriptHost.h和ScriptHost.cpp加入到工程中。(5) 在类CScriptDlg中加入数据成员m_pScHost,其类型为CScriptHost *。(6) 用ClassWizard生成按钮“Load Script”的消息控制函数,编写代码如下:void CScriptDlg:OnLoadscript() CFileDialog dlg(TRUE, "*.txt","*.txt",OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,"Text files (*.txt)&q
47、uot;);if(dlg.DoModal()=IDOK)CString strPath;strPath = dlg.GetPathName();if (strPath.IsEmpty()return;if (m_pScHost != NULL) m_pScHost->m_ps->Close();CWnd *pCalander = GetDlgItem(IDC_CONTROL1);m_pUnknownCtrl = pCalander->GetControlUnknown();m_pScHost = new CScriptHost(m_pUnknownCtrl, L"c
48、ontrol", m_hWnd);HRESULT hr = m_pScHost->CreateScriptEngine();hr = m_pScHost->ParseFile(strPath,L"control");GetDlgItem(IDC_RUNSCRIPT)->EnableWindow(TRUE);GetDlgItem(IDC_RUNSCRIPT)->SetWindowText("Run Script");return;return;在消息控制函数OnLoadscript中,首先打开标准文件对话框,待用户选中脚本
49、文件后,取到文件名,放到变量strPath中,如果原先已经存在引擎对象,则先关闭引擎对象。然后通过CWnd:GetControlUnknown函数取出日历控制的IUnknown接口指针。完成了这些准备工作后,再构造一个CScriptHost对象,把控制的IUnknown接口指针、控制名以及对话框的窗口句柄传到CScriptHost对象中,然后调用其CreateScriptEngine成员函数创建脚本引擎对象,创建完成后,再调用ParseFile成员函数装入脚本文件。装入脚本之后,设置“Run Script”按钮使其接收运行脚本的命令。注意,在OnLoadscript函数返回后,脚本引擎已经创建完成,脚本文件也已经装入到引擎中,但这时脚本代码并没有被运行。(7) 用ClassWizard生成按钮“Ru
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 有限空间作业安全事故案例及安全生产法规知识试题附答案
- 中考化学模拟考试卷(带有答案)
- 供热工程试卷题库及答案
- 2025年检验医院考试试题及答案
- 2025年辽宁中考语法真题及答案
- 特变电工考试试题及答案
- 金沙英语考试试题及答案
- 化学实验活动参与度与兴趣调查试题
- 2025年高考物理全真模拟演练试题(三)
- 公司培训考试题目及答案
- 2025贵州黔西南州民政局公益性岗位招聘模拟试卷及答案详解(典优)
- 一国两制课件
- 隔震支座安装施工方案
- 中药生物安全培训内容课件
- 2024年武汉商学院公开招聘辅导员笔试题含答案
- 捶草印花课件
- 银行反电诈培训课件
- tesol考试的样卷及答案
- DB32-T 5156-2025 零碳园区建设指南
- 外周血T细胞分离技术详解
- 世界现代设计简史-下篇
评论
0/150
提交评论