如何添加对 ATL 的应用程序承载 VBScript 的支持

来源:互联网 发布:小猪cms和baocms 编辑:程序博客网 时间:2024/05/21 11:00

您可以添加类似于 VBA 的脚本编写功能到 ATL 应用程序开销很小使用 Microsoft ActiveX 脚本技术。本文演示了如何创建一个新的 ATL 应用程序或合并 VBScript 支持的一个已有的修改。
回到顶端
更多信息请按照以下步骤以生成并运行该示例: 创建一个新的 ATL COM EXE 项目 (称为 AtlClientApp,或使用现有您要添加对承载 VBScript 支...请按照以下步骤以生成并运行该示例:

创建一个新的 ATL COM EXE 项目 (称为 AtlClientApp,或使用现有您要添加对承载 VBScript 支持此类的项目。
请按照下面的 Microsoft 知识库文章,将一个对话框,添加到您的应用程序中所述步骤操作:
196135  (http://support.microsoft.com/kb/196135/ ) 如何创建使用 ATL 的自动化客户端项目
在 $ ResourceView,中打开对话框,并在其中添加一个编辑框,用户可在其中键入一些 VBScript 中。用鼠标右键单击它,选择属性,并使其"多行"和"想要返回"。
从插入菜单中选择新的 ATL 对象。添加一个简单的对象名 MyObject 为在名称选项卡上,选择属性选项卡上的支持连接点。
添加到您的应用程序调用 MyScriptSite.h 新文件并将下面的代码粘贴到它:
   #include <windows.h>
   #include <activscp.h>

   class CMyScriptSite : public IActiveScriptSite {
   private:
      ULONG m_dwRef;
   public:
      IUnknown *m_pUnkScriptObject;
      ITypeInfo *m_pTypeInfo;

      CMyScriptSite::CMyScriptSite() {
         m_pUnkScriptObject = 0;
         m_pTypeInfo = 0;
         m_dwRef = 1;
      }

      // IUnknown methods...
      virtual HRESULT __stdcall QueryInterface(REFIID riid,
         void **ppvObject) {
         *ppvObject = NULL;
         return E_NOTIMPL;
      }
      virtual ULONG _stdcall AddRef(void) {
         return ++m_dwRef;
      }
      virtual ULONG _stdcall Release(void) {
         if(--m_dwRef == 0) return 0;
         return m_dwRef;
      }

      // IActiveScriptSite methods...
      virtual HRESULT __stdcall GetLCID(LCID *plcid) {
         return S_OK;
      }
  
      virtual HRESULT __stdcall GetItemInfo(LPCOLESTR pstrName,
         DWORD dwReturnMask, IUnknown **ppunkItem, ITypeInfo **ppti) {
         // Is it expecting an ITypeInfo?
         if(ppti) {
            // Default to NULL.
            *ppti = NULL;
        
            // See if asking about ITypeInfo...
            if(dwReturnMask & SCRIPTINFO_ITYPEINFO) {
               *ppti = m_pTypeInfo;
            }
         }
     
         // Is the engine passing an IUnknown buffer?
         if(ppunkItem) {
            // Default to NULL.
            *ppunkItem = NULL;
        
            // Is Script Engine looking for an IUnknown for our object?
            if(dwReturnMask & SCRIPTINFO_IUNKNOWN) {
               // Check for our object name...
               if (!_wcsicmp(L"MyObject", pstrName)) {
                  // Provide our object.
                  *ppunkItem = m_pUnkScriptObject;
                  // Addref our object...
                  m_pUnkScriptObject->AddRef();
               }
            }
         }
     
         return S_OK;
      }
  
      virtual HRESULT __stdcall GetDocVersionString(BSTR *pbstrVersion) {
         return S_OK;
      }
  
      virtual HRESULT __stdcall OnScriptTerminate(
         const VARIANT *pvarResult, const EXCEPINFO *pexcepInfo) {
         return S_OK;
      }
  
      virtual HRESULT __stdcall OnStateChange(SCRIPTSTATE ssScriptState) {
         return S_OK;
      }
  
      virtual HRESULT __stdcall OnScriptError(
         IActiveScriptError *pscriptError) {
         ::MessageBox(NULL, "OnScriptError()", "Error", MB_SETFOREGROUND);    
         return S_OK;
      }
  
      virtual HRESULT __stdcall OnEnterScript(void) {
         return S_OK;
      }
  
      virtual HRESULT __stdcall OnLeaveScript(void) {
         return S_OK;
      }

   };
     

删除在 OnOK() 对话框按钮处理中有任何代码,添加以下代码:
   // Instantiate script site & objects...
   CMyScriptSite *pMySite = new CMyScriptSite;
   CComObject<CMyObject> *pMyObject = new CComObject<CMyObject>;
  
   // Register your type-library
   ITypeLib *ptLib = 0;
   HRVERIFY(LoadTypeLib(L"AtlClientApp.tlb", &ptLib), "LoadTypeLib");
  
   // Initialize your IActiveScriptSite implementation with your
   // object's ITypeInfo...
   ptLib->GetTypeInfoOfGuid(CLSID_MyObject, &pMySite->m_pTypeInfo);
   ptLib->Release();
  
   // Initialize your IActiveScriptSite implementation with your
   // script object's IUnknown interface...
   HRVERIFY(pMyObject->QueryInterface(IID_IUnknown,
      (void **)&pMySite->m_pUnkScriptObject), "IUnknown initialization");
  
   // Start inproc script engine, VBSCRIPT.DLL
   IActiveScript *pAS;
   HRVERIFY(CoCreateInstance(CLSID_VBScript, NULL, CLSCTX_INPROC_SERVER,
      IID_IActiveScript, (void **)&pAS),
      "CoCreateInstance() for CLSID_VBScript");
  
   // Get engine's IActiveScriptParse interface.
   IActiveScriptParse *pASP;
   HRVERIFY(pAS->QueryInterface(IID_IActiveScriptParse, (void **)&pASP),
      "QueryInterface() for IID_IActiveScriptParse");
  
   // Give engine your IActiveScriptSite interface...
   HRVERIFY(pAS->SetScriptSite((IActiveScriptSite *)pMySite),
      "IActiveScript::SetScriptSite()");
  
   // Give the engine a chance to initialize itself...
   HRVERIFY(pASP->InitNew(), "IActiveScriptParse::InitNew()");
  
   // Add a root-level item to the engine's name space...
   HRVERIFY(pAS->AddNamedItem(L"MyObject", SCRIPTITEM_ISVISIBLE |
      SCRIPTITEM_ISSOURCE), "IActiveScript::AddNamedItem()");
  
   // Get text from edit-box...
   HWND editHwnd = GetDlgItem(IDC_EDIT1);
   char szBuf[1024];
   int len = ::GetWindowText(editHwnd, szBuf, 1024);
   szBuf[len] = 0;
  
   // Convert it to a wide-char string...
   WCHAR wcBuf[1024];
   memset(wcBuf, 0, sizeof(WCHAR)*1024);
   MultiByteToWideChar(CP_ACP, 0, szBuf, strlen(szBuf), wcBuf, 1024);
  
   // Parse the code scriptlet...
   EXCEPINFO ei;
   BSTR pParseText = ::SysAllocString(wcBuf);
   HRVERIFY(pASP->ParseScriptText(pParseText, L"MyObject", NULL, NULL, 0,
      0, 0L, NULL, &ei), "ParseScriptText");
   ::SysFreeString(pParseText);
  
   // Set the engine state. This line actually triggers the execution
   // of the script.
   HRVERIFY(pAS->SetScriptState(SCRIPTSTATE_CONNECTED), "SetScriptState");
  
   // Let user know script-run is finished...
   ::MessageBox(NULL, "Script finished, click me to fire event...", "",
      MB_SETFOREGROUND);
  
   // Fire an event...
   pMyObject->Fire_MyEvent();
  
   // Close script and release interfaces...
   pAS->Close();
   pASP->Release();
   pAS->Release();
  
   // Delete site & objects...
   delete pMySite;
   delete pMyObject;
   return 0;
     

 

添加下列内容的正下方 # 相同的文件 (ClientDlg.h) 顶部包含 atlhost.h:
   #include "AtlClientApp.h"
   #include "MyObject.h"
   #include "MyScriptSite.h"
   void HRVERIFY(HRESULT hr, char * msg);
   extern const GUID CLSID_VBScript;
     

 

将以下代码添加到您 ClientDlg.cpp 结尾:
   void HRVERIFY(HRESULT hr, char * msg)
   {
      if(FAILED(hr)) {
         static char buf[1024];
         sprintf(buf, "Error: %08lx, %s", hr, msg);
         ::MessageBox(NULL, buf, "", MB_SETFOREGROUND);
         _exit(0);
      }

   }

   // Script Engine CLSIDs...
   #include <initguid.h>
   DEFINE_GUID(CLSID_VBScript, 0xb54f3741, 0x5b07, 0x11cf, 0xa4, 0xb0, 0x0,
               0xaa, 0x0, 0x4a, 0x55, 0xe8);
     

 

用鼠标右键单击在 ClassView IMyObject 接口上、 添加名为 SayHi 和 SayHi2,在以下两种方法并实现它们,如下所示:

   STDMETHODIMP CMyObject::SayHi()
   {
      ::MessageBox(NULL, "Inside SayHi()", "", MB_SETFOREGROUND);
      return S_OK;
   }

   STDMETHODIMP CMyObject::SayHi2()
   {
      ::MessageBox(NULL, "Inside SayHi2()", "", MB_SETFOREGROUND);
      return S_OK;
   }
     

 

用鼠标右键单击您 IMyObjectEvents 接口上,并添加名为 MyEvent 的方法。转到下一步前, 您应该选择重建全部从生成菜单中即使它不会完全尚未生成。这是的这样您的项目获取更新并 ClassView 将识别您在 $ 下一步中的事件。
在 ClassView,右击您 CMyObject 类,然后选择实现连接点。检查 IMyObjectEvents 接口,然后单击确定。
从生成菜单中选择全部重新生成并运行该示例。在下面的示例在编辑框中的 VBScript 中键入,然后单击运行:
   SayHi

   Sub MyObject_MyEvent
      SayHi2
   End Sub
     

回到顶端
参考Microsoft ActiveX 脚本宿主的详细信息请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章: 221992  (http://s...Microsoft ActiveX 脚本宿主的详细信息请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
221992  (http://support.microsoft.com/kb/221992/ ) 如何添加对 hosing VBScript 向 MFC 应用程序的支持
183698  (http://support.microsoft.com/kb/183698/ ) Axsh.exe 演示如何实现一个活动脚本主机
168214  (http://support.microsoft.com/kb/168214/ ) MFCAXS 实现使用 MFC 的活动脚本主机
回到顶端

原创粉丝点击