zoukankan      html  css  js  c++  java
  • 如何在我们的程序中使用jscript脚本(zz)

    原文地址:http://www.cppprog.com/2009/0406/99.html

    在CSDN上看到有不少人问怎样才能象MS Office一样支持VBA,偶也很感兴趣,可惜Google后发现要支持VBA得付钱给M$才行,象我们这种无产阶级自然是只有想的份啦。

      不过MS还是有点“爱心”D,它给了我们另外一个选择——ActiveX Scripting(后面简称[AS])。

      简单的说[AS]就是:MS来帮我们解析脚本里的基本语句(如if、for、表态式、赋值等),我们负责解释、执行它所不认识的函数,对象。

      下面再简单说一下操作[AS]的流程:

      1. 实例化一个脚本对象(IActiveScript),一般装了IE的电脑上应该都有JScript和VBScript。
    2. 告诉IActiveScript谁来解释脚本中的对象(IActiveScript ::SetScriptSite)
    3. 告诉IActiveScript脚本里会用到哪些对象(用IActiveScript ::AddNamedItem)
    4. 装入脚本(JScript或VBScript代码,UNICODE格式)
    5. 运行脚本(通过设置IActiveScript ::SetScriptState实现)
    6. [AS]在运行脚本过程中如果遇到第3步里告诉它的对象,它就会向我们要此对象的接口以便继续执行(它会调用IActiveScriptSite::GetItemInfo,第2步里告诉它的)。
    7. 打完收工。当然也可以强制停下运行中的脚本(比如不小心编了一个死循环的脚本)。也是通过设置IActiveScript ::SetScriptState实现。

      从上面可以看出,我们的主要工作是实现脚本里的对象的解释工作。在COM编程中,毫无悬念地,这个光荣而又艰巨的任务就又落到了IDispatch身上。IDispatch的生平事迹咱就不介绍了,不明白的去问明白的,都不明白的去Google,心急的可以看后面的示例代码。

      对我们编程的来说,说再多也不如源代码来得直接有效,下面我们就来做一个支持脚本的小程序。这里我们使用BCB来做,其它如VC,GCC当然也行,不过对于快速原型开发方面,BCB绝对是不二选择(广告时间)。

    先看偶写的一个JScript脚本:

    1. var bForward = true;
    2. for(var i=0;i<ScreenWidth-200;i+=100)
    3. {
    4. for(var j=0;j<ScreenHeight-200;j+=10)
    5.     {
    6. var x = i;
    7. var y = bForward? j : (ScreenHeight-200-j)
    8.         MyWin.MoveTo(x,y);
    9.         MyWin.Caption = "X:" + x + " Y:"+y;
    10.         MyWin.Color = (x<<16|y)&0xffffff;
    11.         Sleep(10);
    12.     }
    13.     bForward = !bForward;
    14. }

    此脚本的目的是让一个叫MyWin的窗口从左到右地上下移动,同时改变标题和颜色。

    前面说了MS只帮我们解决脚本语言上的问题,我们来处理对象和函数。在这个脚本里,我们的任务有:ScreenWidth、ScreenHeight、Sleep、MyWin对象以及它的方法属性。

    这里还得说一下IDispatch的调用过程:比如当[AS]执行到MyWin.MoveTo(x,y);时,它先得到MyWin的IDispatch接口(它是怎么得到的?后面会讲先按下不提),然后调用IDispatch的GetIDsOfNames(riid,L"MoveTo",1,lcid,&rgDispId)获得MoveTo对应的"Member Id"(rgDispId参数)。再用这个"Member Id"去调用Invoke(rgDispId,...)。所以我们只需关注GetIDsOfNames和Invoke两个方法即可。

    先编写一个TMyGlobalFunc来处理ScreenWidth、ScreenHeight、Sleep这三个全局函数:

    1. struct TMyGlobalFunc : TDispatch{
    2. enum {itemScreenWidth,itemScreenHeight,itemSleep};
    3. static wchar_t Name[];
    4.     STDMETHOD(GetIDsOfNames)(REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,
    5.             DISPID *rgDispId){
    6. if(lstrcmpW(rgszNames[0],L"ScreenWidth") == 0){
    7.             *rgDispId = itemScreenWidth;
    8.         }
    9. else if(lstrcmpW(rgszNames[0],L"ScreenHeight") == 0) {
    10.             *rgDispId = itemScreenHeight;
    11.         }
    12. else if(lstrcmpW(rgszNames[0],L"Sleep") == 0) {
    13.             *rgDispId = itemSleep;
    14.         }
    15. else
    16. return E_NOTIMPL;
    17. return S_OK;
    18.     }
    19.     STDMETHOD(Invoke)(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,
    20.             DISPPARAMS *pDispParams,
    21.             VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr){
    22. switch(dispIdMember)
    23.         {
    24. case itemScreenWidth:
    25.                 pVarResult->vt=VT_I4;
    26.                 pVarResult->intVal = Screen->Width;
    27. break;
    28. case itemScreenHeight:
    29.                 pVarResult->vt=VT_I4;
    30.                 pVarResult->intVal = Screen->Height;
    31. break;
    32. case itemSleep:
    33. if(pDispParams->cArgs!=1) return DISP_E_BADPARAMCOUNT;
    34. if(pDispParams->rgvarg[0].vt != VT_I4) {
    35.                     *puArgErr = 0;
    36. return DISP_E_TYPEMISMATCH;
    37.                 }
    38.                 Application->ProcessMessages();
    39.                 Sleep(pDispParams->rgvarg[0].intVal);
    40. break;
    41. default:
    42. return DISP_E_MEMBERNOTFOUND;
    43.         }
    44. return S_OK;
    45.     }
    46. };
    47. wchar_t TMyGlobalFunc::Name[]=L"MyGlobalFunc";

    再写个TMyWin来处理MyWin对象的方法和属性,和上面一样

    1. struct TMyWin : TDispatch{
    2. enum {itemCaption,itemColor,itemMoveTo};
    3. static wchar_t Name[];
    4. // IDispatch
    5.     STDMETHOD(GetIDsOfNames)(REFIID riid,LPOLESTR *rgszNames,UINT cNames,LCID lcid,
    6.                                 DISPID *rgDispId){
    7. if(lstrcmpW(rgszNames[0],L"Caption") == 0) {
    8.             *rgDispId = itemCaption;
    9.         }
    10. else if(lstrcmpW(rgszNames[0],L"Color") == 0) {
    11.             *rgDispId = itemColor;
    12.         }
    13. else if(lstrcmpW(rgszNames[0],L"MoveTo") == 0) {
    14.             *rgDispId = itemMoveTo;
    15.         }
    16. else
    17. return E_NOTIMPL;
    18. return S_OK;
    19.     }
    20.     STDMETHOD(Invoke)(DISPID dispIdMember,REFIID riid,LCID lcid,WORD wFlags,
    21.                       DISPPARAMS *pDispParams,
    22.                       VARIANT *pVarResult,EXCEPINFO *pExcepInfo,UINT *puArgErr){
    23. switch(dispIdMember)
    24.         {
    25. case itemCaption:
    26.           {
    27. if(wFlags==DISPATCH_PROPERTYGET)
    28.             {
    29.                 pVarResult->vt = VT_BSTR;
    30.                 pVarResult->bstrVal = GetCaption();
    31.             }
    32. else if(wFlags==DISPATCH_PROPERTYPUT)
    33.             {
    34. if(pDispParams->cArgs!=1) return DISP_E_BADPARAMCOUNT;
    35. if(pDispParams->rgvarg[0].vt != VT_BSTR) {
    36.                     *puArgErr = 0;
    37. return DISP_E_TYPEMISMATCH;
    38.                 }
    39.                 SetCaption(pDispParams->rgvarg[0].bstrVal);
    40.             }
    41. else
    42. return DISP_E_MEMBERNOTFOUND;
    43. break;
    44.           }
    45. case itemColor:
    46.           {
    47. if(wFlags==DISPATCH_PROPERTYGET)
    48.             {
    49.                 pVarResult->vt = VT_I4;
    50.                 pVarResult->intVal = GetColor();
    51.             }
    52. else if(wFlags==DISPATCH_PROPERTYPUT)
    53.             {
    54. if(pDispParams->cArgs!=1) return DISP_E_BADPARAMCOUNT;
    55. if(pDispParams->rgvarg[0].vt != VT_I4) {
    56.                     *puArgErr = 0;
    57. return DISP_E_TYPEMISMATCH;
    58.                 }
    59.                 SetColor(pDispParams->rgvarg[0].intVal);
    60.             }
    61. else
    62. return DISP_E_MEMBERNOTFOUND;
    63. break;
    64.           }
    65. case itemMoveTo:
    66.           {
    67. if(wFlags==DISPATCH_METHOD)
    68.             {
    69. if(pDispParams->cArgs!=2) return DISP_E_BADPARAMCOUNT;
    70. if(pDispParams->rgvarg[0].vt != VT_I4) {
    71.                     *puArgErr = 0;
    72. return DISP_E_TYPEMISMATCH;
    73.                 }
    74. else if(pDispParams->rgvarg[1].vt != VT_I4){
    75.                     *puArgErr = 1;
    76. return DISP_E_TYPEMISMATCH;
    77.                 }
    78.                 MoveTo( pDispParams->rgvarg[1].intVal,
    79.                         pDispParams->rgvarg[0].intVal);
    80.             }
    81. else
    82. return DISP_E_MEMBERNOTFOUND;
    83. break;
    84.           }
    85. default:
    86. return DISP_E_MEMBERNOTFOUND;
    87.         }
    88. return S_OK;
    89.     }
    90. //  TMyWin上所有的方法属性都对这个TForm *fm_Opt操作
    91.     TMyWin(TForm *fm_Opt) : TDispatch(),m_Form(fm_Opt){ ; }  
    92.     BSTR GetCaption(){
    93. return WideString(m_Form->Caption).Detach();
    94.     }
    95. void SetCaption(BSTR bstrCaption){
    96.         m_Form->Caption = bstrCaption;
    97.     }
    98. int GetColor(){
    99. return (int)m_Form->Color;
    100.     }
    101. void SetColor(int iColor){
    102.         m_Form->Color = TColor(iColor);
    103.     }
    104. void MoveTo(int X,int Y){
    105.         m_Form->Left=X;
    106.         m_Form->Top=Y;
    107.     }
    108. private:
    109.     TForm *m_Form;
    110. };
    111. wchar_t TMyWin::Name[]=L"MyWin";

    主要任务完成,接着我们要实现IActiveScriptSite,它用于上面所说的第2步和第6步。[AS]解析上面的脚本时遇到MyWin及ScreenWidth、ScreenHeight、Sleep时会通过GetItemInfo向它要接口,它则负责把我们刚才写的IDispatch喂给[AS]。
    这个IActiveScriptSite要包含头文件#include <activscp.h>

    1. struct TMyActiveScriptSite
    2.     : IActiveScriptSite
    3. {
    4.     TMyActiveScriptSite(TMyWin *pMyWin,TMyGlobalFunc *pMyGlobalFunc)
    5.         : m_iRefCount(1),m_pMyWin(pMyWin),m_pMyGlobalFunc(pMyGlobalFunc){
    6.     }
    7. // IUNKnown,不得不写
    8. HRESULT __stdcall QueryInterface(REFIID iid, void **ppv){
    9. if(iid==IID_IUnknown||iid==IID_IActiveScriptSite)
    10.         {
    11.             *ppv=this;
    12.             AddRef();
    13. return S_OK;
    14.         }
    15.         *ppv=NULL;
    16. return E_NOINTERFACE;
    17.     }
    18. ULONG __stdcall AddRef(void) {
    19. return ++m_iRefCount;
    20.     }
    21. ULONG __stdcall Release(void) {
    22. if(--m_iRefCount==0){
    23. delete this;
    24. return 0;
    25.         }
    26. return m_iRefCount;
    27.     }
    28. // IActiveScriptSite
    29.     STDMETHOD(GetLCID)(LCID* /**//*plcid*/) {
    30. return E_NOTIMPL;
    31.     }
    32. //主要的就是这个
    33.     STDMETHOD(GetItemInfo)(LPCOLESTR pstrName,
    34. DWORD dwReturnMask,
    35.                           IUnknown** ppiunkItem,
    36.                           ITypeInfo** ppti) {
    37. if( (dwReturnMask & SCRIPTINFO_ITYPEINFO)!=0 ){
    38.             *ppti = NULL;
    39. return E_FAIL;
    40.         }
    41. if( (dwReturnMask & SCRIPTINFO_IUNKNOWN)==0 ) return E_FAIL;
    42. if( ppiunkItem==NULL ) return E_POINTER;
    43.         *ppiunkItem = NULL;
    44. if( lstrcmpW( pstrName, TMyWin::Name )==0 ) {
    45. //[AS]要MyWin,送上!
    46.             m_pMyWin->AddRef();
    47.             *ppiunkItem = m_pMyWin;
    48. return S_OK;
    49.         }
    50. else if( lstrcmpW( pstrName, TMyGlobalFunc::Name )==0 ) { 
    51. //[AS]要MyGlobalFunc,送上!
    52.             m_pMyGlobalFunc->AddRef();
    53.             *ppiunkItem = m_pMyGlobalFunc;
    54. return S_OK;
    55.         }
    56. return E_FAIL;   //要其它的,没有!
    57.    }
    58.    STDMETHOD(GetDocVersionString)(BSTR* pbstrVersion) {
    59. if( pbstrVersion==NULL ) return E_POINTER;
    60.       *pbstrVersion = ::SysAllocString(OLESTR("Script 1.0"));
    61. return S_OK;
    62.    }
    63.    STDMETHOD(OnScriptTerminate)(
    64. const VARIANT* /**//*pvarResult*/,
    65. const EXCEPINFO* /**//*pexcepinfo*/) {
    66. return S_OK;
    67.    }
    68.    STDMETHOD(OnStateChange)(SCRIPTSTATE /**//*ssScriptState*/) {
    69. return S_OK;
    70.    }
    71. // 脚本里有错误时会调用OnScriptError
    72.    STDMETHOD(OnScriptError)(IActiveScriptError* pScriptError) {
    73.       EXCEPINFO e;
    74. DWORD dwContext;
    75. ULONG ulLine;
    76. LONG lPos;
    77.       pScriptError->GetExceptionInfo(&e);
    78.       pScriptError->GetSourcePosition(&dwContext, &ulLine, &lPos);
    79. char *pstrFormat = "An error occured while parsing script:"
    80. " Source: %ws Error: %08X Description: %ws Line: %d";
    81. char pstrStr[1024];
    82.       ::wsprintf( pstrStr, pstrFormat,
    83.          e.bstrSource,
    84.          e.scode,
    85.          e.bstrDescription,
    86.          ulLine+1);
    87.       ::MessageBox(::GetActiveWindow(), pstrStr,
    88.         _T("Compile Error"), MB_OK | MB_ICONEXCLAMATION | MB_SETFOREGROUND);
    89. return S_OK;
    90.    }
    91.    STDMETHOD(OnEnterScript)() {
    92. return S_OK;
    93.    }
    94.    STDMETHOD(OnLeaveScript)() {
    95. return S_OK;
    96.    }
    97. private:
    98.     TMyWin *m_pMyWin;
    99.     TMyGlobalFunc *m_pMyGlobalFunc;
    100. int m_iRefCount;
    101. };

    万事俱备,就等执行了:
    打开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.     TComInterface<IActiveScriptParse> pASP(pAS);
    8. if(!pASP) return;
    9.     pASP->InitNew();
    10. // 我们的劳动成果在这里
    11.     TComInterface<TMyWin> pDispatch_MyWin = new TMyWin(this);
    12.     TComInterface<TMyGlobalFunc> pDispatch_MyGlobalFunc = new TMyGlobalFunc;
    13.     TComInterface<TMyActiveScriptSite> pActiveScriptSite_Mine = 
    14. new TMyActiveScriptSite(pDispatch_MyWin,pDispatch_MyGlobalFunc);
    15. //第二步,告诉IActiveScript谁来解释脚本中的对象
    16.   pAS->SetScriptSite(pActiveScriptSite_Mine);
    17. //第三步,告诉IActiveScript脚本里会用到哪些对象
    18.     pAS->AddNamedItem(TMyWin::Name,SCRIPTITEM_ISVISIBLE);  //会用到”MyWin”
    19. //多了一个SCRIPTITEM_GLOBALMEMBERS,意思是如果遇到全局函数就向”MyGlobalFunc”要。
    20.     pAS->AddNamedItem(TMyGlobalFunc::Name,
    21.         SCRIPTITEM_ISVISIBLE|SCRIPTITEM_GLOBALMEMBERS);
    22. //第四步,装入脚本
    23.     pASP->ParseScriptText(WideString(mmoScript->Lines->Text),
    24.                                   NULL,
    25.                                   NULL,
    26.                                   NULL,
    27.                                   0,
    28.                                   0,
    29.                                   0,
    30.                                   NULL,
    31.                                   NULL);
    32. //第五步,运行脚本
    33.   pAS->SetScriptState(SCRIPTSTATE_STARTED);
    34.     pAS->Close();
    35. }

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

    Unit1.cpp

    1. //---------------------------------------------------------------------------
    2. #include <vcl.h>
    3. #pragma hdrstop
    4. #include "Unit1.h"
    5. #include "Script.h"
    6. #include <utilcls.h>
    7. //---------------------------------------------------------------------------
    8. #pragma package(smart_init)
    9. #pragma resource "*.dfm"
    10. TForm1 *Form1;
    11. //---------------------------------------------------------------------------
    12. __fastcall TForm1::TForm1(TComponent* Owner)
    13.     : TForm(Owner)
    14. {
    15. }
    16. //---------------------------------------------------------------------------
    17. void __fastcall TForm1::btnRunClick(TObject *Sender)
    18. {
    19.     TComInterface<IActiveScript> pAS;
    20.     pAS.CreateInstance(L"JScript");
    21. if(!pAS) return;
    22.     TComInterface<IActiveScriptParse> pASP(pAS);
    23. if(!pASP) return;
    24.     pASP->InitNew();
    25.     TComInterface<TMyWin> pDispatch_MyWin=new TMyWin(this);
    26.     TComInterface<TMyGlobalFunc> pDispatch_MyGlobalFunc = new TMyGlobalFunc;
    27.     TComInterface<IActiveScriptSite> pActiveScriptSite_Mine = 
    28. new TMyActiveScriptSite(pDispatch_MyWin,pDispatch_MyGlobalFunc);
    29.     pAS->SetScriptSite(pActiveScriptSite_Mine);
    30.     pAS->AddNamedItem(TMyWin::Name,SCRIPTITEM_ISVISIBLE);
    31.     pAS->AddNamedItem(TMyGlobalFunc::Name,
    32.         SCRIPTITEM_ISVISIBLE|SCRIPTITEM_GLOBALMEMBERS);
    33.     pASP->ParseScriptText(WideString(mmoScript->Lines->Text),
    34.                                   NULL,
    35.                                   NULL,
    36.                                   NULL,
    37.                                   0,
    38.                                   0,
    39.                                   0,
    40.                                   NULL,
    41.                                   NULL);
    42.     pAS->SetScriptState(SCRIPTSTATE_STARTED);
    43.     pAS->Close();
    44. }
    45. //---------------------------------------------------------------------------
  • 相关阅读:
    k8s用kubectl管理应用升级,服务发布与回滚,扩缩容
    K8s遇到问题解决思路
    Kafka常用命令之kafka-topics.sh
    Kafka常用命令之kafka-console-consumer.sh
    maven idea设置查找依赖优先从指定的本地仓库获取
    Java isAlive()方法的作用
    intellij 格式化 代码
    kafka后台启动的命令
    Kafka 集群部署,启动,关闭,命令行操作
    jquery请求ajax对返回数据解析
  • 原文地址:https://www.cnblogs.com/strinkbug/p/1753541.html
Copyright © 2011-2022 走看看