在自己的程序中加入脚本支持(二)

本文介绍如何在BCB中创建VCL Form应用程序,并通过TActiveScript接口执行JScript代码,实现动态改变窗口标题、颜色及位置等功能。
部署运行你感兴趣的模型镜像

万事俱备,就等执行了:
打开BCB,新建一VCL Form Application。
在默认的Form1上加入一个TMemo改名 为:mmoScript;加入一个TButton改名为btnRun。 btnRun->OnClick代码:
偷懒用到了 TComInterface,要包含: #include <utilcls.h>

1. void __fastcall TForm1::btnRunClick(TObject *Sender)
2. {
3.     TComInterface<IActiveScript> pAS;
4.     // 第一步,实例化Jscript(同学们也可以试试 VBScript)
5.     pAS.CreateInstance(L"JScript");   
6.     if(!pAS) return;
7.  
8.     TComInterface<IActiveScriptParse> pASP(pAS);
9.     if(!pASP) return;
10.  
11.     pASP->InitNew();
12.  
13.     // 我们的劳动成果在这里
14.     TComInterface<TMyWin> pDispatch_MyWin = new TMyWin(this);
15.     TComInterface<TMyGlobalFunc> pDispatch_MyGlobalFunc = new TMyGlobalFunc;
16.     TComInterface<TMyActiveScriptSite> pActiveScriptSite_Mine = 
17.         new TMyActiveScriptSite(pDispatch_MyWin,pDispatch_MyGlobalFunc);
18.     
19.   //第二步,告诉IActiveScript谁来解释脚本中的对象
20.    pAS->SetScriptSite(pActiveScriptSite_Mine);
21.   
22.     //第三步,告诉IActiveScript脚本里会用到哪些对象
23.     pAS->AddNamedItem(TMyWin::Name,SCRIPTITEM_ISVISIBLE);  //会用到”MyWin”
24.     //多了一个SCRIPTITEM_GLOBALMEMBERS,意思是如果遇到全局函数就向”MyGlobalFunc”要。
25.     pAS->AddNamedItem(TMyGlobalFunc::Name,
26.         SCRIPTITEM_ISVISIBLE|SCRIPTITEM_GLOBALMEMBERS);
27.     
28.     // 第四步,装入脚本
29.     pASP->ParseScriptText(WideString(mmoScript->Lines->Text),
30.                                   NULL,
31.                                   NULL,
32.                                   NULL,
33.                                   0,
34.                                   0,
35.                                   0,
36.                                   NULL,
37.                                   NULL);
38.  
39.   //第五步,运行脚本
40.   pAS->SetScriptState(SCRIPTSTATE_STARTED);
41.   
42.     pAS->Close();
43. }

编译,运行。
把写的 Jscript代码拷贝到mmoScript里然后按btnRun运行可以看到效果。当然也可以修改脚本弄点更好玩的花样出来,呵呵。
最后还要多 说一句关于ParseScriptText,用好它后面的几个参数。看MSDN,修改其中一个参数这段代码就可以用作表态式解析了。

附上 完整代码:
Script.h

1. #ifndef SCRIPT_H
2. #define SCRIPT_H
3. //=============================================================
4. #include <tchar.h>
5. #include <activscp.h>
6.  
7. // TDispatch:简单实现 IDispath的所有方法,用于作自动化对象的基类。
8. struct TDispatch : IDispatch{
9.     TDispatch():m_iRefCount(1){;}
10.     ~TDispatch(){;}
11.     // IUNKnown
12.     HRESULT __stdcall QueryInterface(REFIID iid, void **ppv){
13.         if(iid==IID_IUnknown||iid==IID_IDispatch)
14.         {
15.             *ppv=this;
16.             AddRef();
17.             return S_OK;
18.         }
19.         *ppv=NULL;
20.         return E_NOINTERFACE;
21.     }
22.     ULONG __stdcall AddRef(void) {
23.         return ++m_iRefCount;
24.     }
25.     ULONG __stdcall Release(void) {
26.         if(--m_iRefCount==0){
27.             delete this;
28.             return 0;
29.         }
30.         return m_iRefCount;
31.     }
32.  
33.     // IDispatch
34.     STDMETHOD(GetTypeInfoCount)(UINT *pctinfo){return S_OK;}
35.     STDMETHOD(GetTypeInfo)(UINT iTInfo,
36.             LCID lcid,ITypeInfo **ppTInfo){return S_OK;}
37.     STDMETHOD(GetIDsOfNames)(REFIID riid,
38.             LPOLESTR *rgszNames,UINT cNames,LCID lcid,DISPID *rgDispId){
39.         return E_NOTIMPL;
40.     }
41.  
42.     STDMETHOD(Invoke)(DISPID dispIdMember,REFIID riid,
43.             LCID lcid,WORD wFlags,
44.             DISPPARAMS *pDispParams,
45.             VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr){
46.         return S_OK;
47.     }
48.     private:
49.     int m_iRefCount;
50. };
51.  
52. // TMyWin,实现MyWin对象类,解释Caption,Color 属性,MoveTo方法
53. struct TMyWin : TDispatch{
54.     enum {itemCaption,itemColor,itemMoveTo};
55.     static wchar_t Name[];
56.     // IDispatch
57.     STDMETHOD(GetIDsOfNames)(REFIID riid,
58.             LPOLESTR *rgszNames,UINT cNames,LCID lcid,
59.             DISPID *rgDispId){
60.         if(lstrcmpW(rgszNames[0],L"Caption") == 0)
61.         {
62.             *rgDispId = itemCaption;
63.         }
64.         else if(lstrcmpW(rgszNames[0],L"Color") == 0)
65.         {
66.             *rgDispId = itemColor;
67.         }
68.         else if(lstrcmpW(rgszNames[0],L"MoveTo") == 0)
69.         {
70.             *rgDispId = itemMoveTo;
71.         }
72.         else
73.             return E_NOTIMPL;
74.         return S_OK;
75.     }
76.  
77.     STDMETHOD(Invoke)(DISPID dispIdMember,
78.             REFIID riid,LCID lcid,WORD wFlags,
79.             DISPPARAMS *pDispParams,
80.             VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr){
81.         switch(dispIdMember)
82.         {
83.             case itemCaption:
84.                 {
85.                     if(wFlags==DISPATCH_PROPERTYGET)
86.                     {
87.                         pVarResult->vt = VT_BSTR;
88.                         pVarResult->bstrVal = GetCaption();
89.                     }
90.                     else if(wFlags==DISPATCH_PROPERTYPUT)
91.                     {
92.                         if(pDispParams->cArgs!=1) return DISP_E_BADPARAMCOUNT;
93.                         if(pDispParams->rgvarg[0].vt != VT_BSTR) {
94.                             *puArgErr = 0;
95.                             return DISP_E_TYPEMISMATCH;
96.                         }
97.                         SetCaption(pDispParams->rgvarg[0].bstrVal);
98.                     }
99.                     else
100.                         return DISP_E_MEMBERNOTFOUND;
101.                     break;
102.                 }
103.             case itemColor:
104.                 {
105.                     if(wFlags==DISPATCH_PROPERTYGET)
106.                     {
107.                         pVarResult->vt = VT_I4;
108.                         pVarResult->intVal = GetColor();
109.                     }
110.                     else if(wFlags==DISPATCH_PROPERTYPUT)
111.                     {
112.                         if(pDispParams->cArgs!=1) return DISP_E_BADPARAMCOUNT;
113.                         if(pDispParams->rgvarg[0].vt != VT_I4) {
114.                             *puArgErr = 0;
115.                             return DISP_E_TYPEMISMATCH;
116.                         }
117.                         SetColor(pDispParams->rgvarg[0].intVal);
118.                     }
119.                     else
120.                         return DISP_E_MEMBERNOTFOUND;
121.                     break;
122.                 }
123.             case itemMoveTo:
124.                 {
125.                     if(wFlags==DISPATCH_METHOD)
126.                     {
127.                         if(pDispParams->cArgs!=2) return DISP_E_BADPARAMCOUNT;
128.                         if(pDispParams->rgvarg[0].vt != VT_I4) {
129.                             *puArgErr = 0;
130.                             return DISP_E_TYPEMISMATCH;
131.                         }
132.                         else if(pDispParams->rgvarg[1].vt != VT_I4){
133.                             *puArgErr = 1;
134.                             return DISP_E_TYPEMISMATCH;
135.                         }
136.                         MoveTo( pDispParams->rgvarg[1].intVal,
137.                                 pDispParams->rgvarg[0].intVal);
138.                     }
139.                     else
140.                         return DISP_E_MEMBERNOTFOUND;
141.                     break;
142.                 }
143.             default:
144.                 return DISP_E_MEMBERNOTFOUND;
145.         }
146.         return S_OK;
147.     }
148.  
149.     //  TMyWin
150.     TMyWin(TForm *fm_Opt) : TDispatch(),m_Form(fm_Opt){ ; }
151.  
152.     BSTR GetCaption(){
153.         return WideString(m_Form->Caption).Detach();
154.     }
155.     void SetCaption(BSTR bstrCaption){
156.         m_Form->Caption = bstrCaption;
157.     }
158.     int GetColor(){
159.         return (int)m_Form->Color;
160.     }
161.     void SetColor(int iColor){
162.         m_Form->Color = TColor(iColor);
163.     }
164.  
165.     void MoveTo(int X,int Y){
166.         m_Form->Left=X;
167.         m_Form->Top=Y;
168.     }
169.  
170.     private:
171.     TForm *m_Form;
172. };
173. wchar_t TMyWin::Name[]=L"MyWin";
174.  
175. struct TMyGlobalFunc : TDispatch{
176.     enum {itemScreenWidth,itemScreenHeight,itemSleep};
177.     static wchar_t Name[];
178.     STDMETHOD(GetIDsOfNames)(REFIID riid,
179.             LPOLESTR *rgszNames,UINT cNames,LCID lcid,
180.             DISPID *rgDispId){
181.         if(lstrcmpW(rgszNames[0],L"ScreenWidth") == 0)
182.         {
183.             *rgDispId = itemScreenWidth;
184.         }
185.         else if(lstrcmpW(rgszNames[0],L"ScreenHeight") == 0)
186.         {
187.             *rgDispId = itemScreenHeight;
188.         }
189.         else if(lstrcmpW(rgszNames[0],L"Sleep") == 0)
190.         {
191.             *rgDispId = itemSleep;
192.         }
193.         else
194.             return E_NOTIMPL;
195.         return S_OK;
196.     }
197.  
198.     STDMETHOD(Invoke)(DISPID dispIdMember,
199.             REFIID riid,LCID lcid,WORD wFlags,
200.             DISPPARAMS *pDispParams,
201.             VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr){
202.         switch(dispIdMember)
203.         {
204.             case itemScreenWidth:
205.                 pVarResult->vt=VT_I4;
206.                 pVarResult->intVal = Screen->Width;
207.                 break;
208.             case itemScreenHeight:
209.                 pVarResult->vt=VT_I4;
210.                 pVarResult->intVal = Screen->Height;
211.                 break;
212.             case itemSleep:
213.                 if(pDispParams->cArgs!=1) return DISP_E_BADPARAMCOUNT;
214.                 if(pDispParams->rgvarg[0].vt != VT_I4) {
215.                     *puArgErr = 0;
216.                     return DISP_E_TYPEMISMATCH;
217.                 }
218.                 Application->ProcessMessages();
219.                 Sleep(pDispParams->rgvarg[0].intVal);
220.                 break;
221.             default:
222.                 return DISP_E_MEMBERNOTFOUND;
223.         }
224.         return S_OK;
225.     }
226. };
227. wchar_t TMyGlobalFunc::Name[]=L"MyGlobalFunc";
228.  
229. struct TMyActiveScriptSite
230. : IActiveScriptSite
231. {
232.     TMyActiveScriptSite(TMyWin *pMyWin,TMyGlobalFunc *pMyGlobalFunc)
233.         : m_iRefCount(1),m_pMyWin(pMyWin),
234.         m_pMyGlobalFunc(pMyGlobalFunc){
235.         }
236.  
237.     // IUNKnown
238.     HRESULT __stdcall QueryInterface(REFIID iid, void **ppv){
239.         if(iid==IID_IUnknown||iid==IID_IActiveScriptSite)
240.         {
241.             *ppv=this;
242.             AddRef();
243.             return S_OK;
244.         }
245.         *ppv=NULL;
246.         return E_NOINTERFACE;
247.     }
248.     ULONG __stdcall AddRef(void) {
249.         return ++m_iRefCount;
250.     }
251.     ULONG __stdcall Release(void) {
252.         if(--m_iRefCount==0){
253.             delete this;
254.             return 0;
255.         }
256.         return m_iRefCount;
257.     }
258.  
259.     // IActiveScriptSite
260.     STDMETHOD(GetLCID)(LCID* /**//*plcid*/) {
261.         return E_NOTIMPL;
262.     }
263.  
264.     STDMETHOD(GetItemInfo)(LPCOLESTR pstrName,
265.             DWORD dwReturnMask,
266.             IUnknown** ppiunkItem,
267.             ITypeInfo** ppti) {
268.         if( (dwReturnMask & SCRIPTINFO_ITYPEINFO)!=0 ){
269.             *ppti = NULL;
270.             return E_FAIL;
271.         }
272.         if( (dwReturnMask & SCRIPTINFO_IUNKNOWN)==0 ) return E_FAIL;
273.         if( ppiunkItem==NULL ) return E_POINTER;
274.         *ppiunkItem = NULL;
275.         if( lstrcmpW( pstrName, TMyWin::Name )==0 ) {
276.             m_pMyWin->AddRef();
277.             *ppiunkItem = m_pMyWin;
278.             return S_OK;
279.         }
280.         else if( lstrcmpW( pstrName, TMyGlobalFunc::Name )==0 ) {
281.             m_pMyGlobalFunc->AddRef();
282.             *ppiunkItem = m_pMyGlobalFunc;
283.             return S_OK;
284.         }
285.         return E_FAIL;
286.     }
287.  
288.     STDMETHOD(GetDocVersionString)(BSTR* pbstrVersion) {
289.         if( pbstrVersion==NULL ) return E_POINTER;
290.         *pbstrVersion = ::SysAllocString(OLESTR("Script 1.0"));
291.         return S_OK;
292.     }
293.  
294.     STDMETHOD(OnScriptTerminate)(
295.             const VARIANT* /**//*pvarResult*/,
296.             const EXCEPINFO* /**//*pexcepinfo*/) {
297.         return S_OK;
298.     }
299.  
300.     STDMETHOD(OnStateChange)(SCRIPTSTATE /**//*ssScriptState*/) {
301.         return S_OK;
302.     }
303.  
304.     STDMETHOD(OnScriptError)(IActiveScriptError* pScriptError) {
305.         EXCEPINFO e;
306.         DWORD dwContext;
307.         ULONG ulLine;
308.         LONG lPos;
309.         pScriptError->GetExceptionInfo(&e);
310.         pScriptError->GetSourcePosition(&dwContext, &ulLine, &lPos);
311.         char *pstrFormat = "An error occured while parsing script:"
312.                             " Source: %ws Error: %08X Description: %ws Line: %d";
313.         char pstrStr[1024];
314.         ::wsprintf( pstrStr, pstrFormat,
315.                 e.bstrSource,
316.                 e.scode,
317.                 e.bstrDescription,
318.                 ulLine+1);
319.         ::MessageBox(::GetActiveWindow(), pstrStr,
320.             _T("Compile Error"), MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
321.         return S_OK;
322.     }
323.  
324.     STDMETHOD(OnEnterScript)() {
325.         return S_OK;
326.     }
327.  
328.     STDMETHOD(OnLeaveScript)() {
329.         return S_OK;
330.     }
331.     private:
332.     TMyWin *m_pMyWin;
333.     TMyGlobalFunc *m_pMyGlobalFunc;
334.     int m_iRefCount;
335. };
336. //=============================================================
337. #endif

Unit1.cpp

1. //---------------------------------------------------------------------------
2.  
3. #include <vcl.h>
4. #pragma hdrstop
5.  
6. #include "Unit1.h"
7. #include "Script.h"
8. #include <utilcls.h>
9. //---------------------------------------------------------------------------
10. #pragma package(smart_init)
11. #pragma resource "*.dfm"
12. TForm1 *Form1;
13. //---------------------------------------------------------------------------
14. __fastcall TForm1::TForm1(TComponent* Owner)
15.     : TForm(Owner)
16. {
17. }
18. //---------------------------------------------------------------------------
19. void __fastcall TForm1::btnRunClick(TObject *Sender)
20. {
21.     TComInterface<IActiveScript> pAS;
22.     pAS.CreateInstance(L"JScript");
23.     if(!pAS) return;
24.  
25.     TComInterface<IActiveScriptParse> pASP(pAS);
26.     if(!pASP) return;
27.  
28.     pASP->InitNew();
29.  
30.     TComInterface<TMyWin> pDispatch_MyWin=new TMyWin(this);
31.     TComInterface<TMyGlobalFunc> pDispatch_MyGlobalFunc = new TMyGlobalFunc;
32.     TComInterface<IActiveScriptSite> pActiveScriptSite_Mine = 
33.         new TMyActiveScriptSite(pDispatch_MyWin,pDispatch_MyGlobalFunc);
34.  
35.     pAS->SetScriptSite(pActiveScriptSite_Mine);
36.     
37.     pAS->AddNamedItem(TMyWin::Name,SCRIPTITEM_ISVISIBLE);
38.     pAS->AddNamedItem(TMyGlobalFunc::Name,
39.         SCRIPTITEM_ISVISIBLE|SCRIPTITEM_GLOBALMEMBERS);
40.  
41.     pASP->ParseScriptText(WideString(mmoScript->Lines->Text),
42.                                   NULL,
43.                                   NULL,
44.                                   NULL,
45.                                   0,
46.                                   0,
47.                                   0,
48.                                   NULL,
49.                                   NULL);
50.     pAS->SetScriptState(SCRIPTSTATE_STARTED);
51.  
52.     pAS->Close();
53. }
54. //---------------------------------------------------------------------------
55.

您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值