博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
如何添加到 MFC 应用程序破坏 VBScript 的支持
阅读量:5929 次
发布时间:2019-06-19

本文共 7428 字,大约阅读时间需要 24 分钟。

您可以添加 MFC 应用程序开销很小,使用 Microsoft ActiveX 脚本技术类似于 VBA 的脚本编写功能。
本文演示如何创建新的 MFC 应用程序中,或修改现有,合并了 VBScript 的支持。
|

更多信息

请按照以下步骤来生成并运行该示例:
  1. 创建新 MFC 对话框基于的应用程序,或使用要添加脚本的支持已有的应用程序。
  2. 向对话框,添加一个编辑框和按钮,启用"需要返回"和"多行"编辑框中的属性中的样式。
  3. 使用成员变量选项卡下类向导 (CTRL-W),IDC_EDIT1 相关联的类型名为 m_edit1 的 CEdit 成员变量。
  4. 类向导用于创建一个名为 MyScriptObject,来自 CCmdTarget,与支持自动化的新类。如果您看到一个 ODL 文件有关的警告,请单击确定。
  5. 类向导的自动化选项卡上,在下选择 MyScriptObject,,并添加下面的方法:
    long gcd(long a, long b);
    void HelpAbout() ;
    void ShowValue (LPCTSTR 提示,长时间 n) ;
  6. 实现 gcd、 HelpAbout 和 ShowValue,如下所示:
    long MyScriptObject::gcd(long a, long b)    {      int l, h, t;      if(a < b) {         l = a;         h = b;      }      else if(a > b) {         l = b;         h = a;      }      else return a;      while(h%l != 0) {         t = l;         l = (h%l);         h = t;      }      return l;   }   void MyScriptObject::HelpAbout()    {      AfxMessageBox("HelpAbout: My Script Object!", 0x10000);   }   void MyScriptObject::ShowValue(LPCTSTR prompt, long n)    {      CString str;      str.Format("%s%d", prompt, n);      AfxMessageBox(str, MB_SETFOREGROUND);   }
  7. 打开 MyScriptObject.h,并移动虚拟析构函数 ~ MyScriptObject 类的受保护的分区中的公共部分。
  8. 双击对话框按钮来创建一个处理程序函数,并实现它,如下所示:
    // Initialize our IActiveScriptSite implementation with your   // script object's IUnknown interface...   g_iActiveScriptSite.m_pUnkScriptObject =       m_myScriptObject.GetInterface(&IID_IUnknown);   // Start inproc script engine, VBSCRIPT.DLL   HRVERIFY(CoCreateInstance(CLSID_VBScript, NULL, CLSCTX_INPROC_SERVER,       IID_IActiveScript, (void **)&m_iActiveScript),       "CoCreateInstance() for CLSID_VBScript");   // Get engine's IActiveScriptParse interface.   HRVERIFY(m_iActiveScript->QueryInterface(IID_IActiveScriptParse,       (void **)&m_iActiveScriptParse),       "QueryInterface() for IID_IActiveScriptParse");   // Give engine our IActiveScriptSite interface...   HRVERIFY(m_iActiveScript->SetScriptSite(&g_iActiveScriptSite),       "IActiveScript::SetScriptSite()");   // Give the engine a chance to initialize itself...   HRVERIFY(m_iActiveScriptParse->InitNew(),      "IActiveScriptParse::InitNew()");   // Add a root-level item to the engine's name space...   HRVERIFY(m_iActiveScript->AddNamedItem(L"MyObject",       SCRIPTITEM_ISVISIBLE | SCRIPTITEM_ISSOURCE),      "IActiveScript::AddNamedItem()");	   // Get script code...   CString csScriptText;   m_edit1.GetWindowText(csScriptText);   // Parse the code scriptlet...   EXCEPINFO ei;   BSTR pParseText = csScriptText.AllocSysString();   m_iActiveScriptParse->ParseScriptText(pParseText, L"MyObject", NULL,      NULL, 0, 0, 0L, NULL, &ei);   // Set the engine state. This line actually triggers the execution   // of the script.   m_iActiveScript->SetScriptState(SCRIPTSTATE_CONNECTED);   // Release engine...   m_iActiveScriptParse->Release();   m_iActiveScript->Release();
  9. 打开您 [projectname]Dlg.h 文件并将下面的成员变量添加到您的类的公共部分:
    MyScriptObject m_myScriptObject;   IActiveScript *m_iActiveScript;   IActiveScriptParse *m_iActiveScriptParse;
  10. 也在 [projectname]Dlg.h,添加下面的 #include 语句,您的类声明之前:
    // Include ActiveX Script definitions...   #include 
    // Include definition for MyScriptObject... #include "MyScriptObject.h"
  11. 将以下代码添加到您 [只是之前的按钮处理程序实现,在 projectname]Dlg.cpp 文件:
    // Your IActiveScriptSite implementation...class MyActiveScriptSite : public IActiveScriptSite {private:   ULONG m_dwRef; // Reference countpublic:   IUnknown *m_pUnkScriptObject; // Pointer to your object that is exposed                                 // to the script engine in GetItemInfo().      MyActiveScriptSite::MyActiveScriptSite() {m_dwRef = 1;}   MyActiveScriptSite::~MyActiveScriptSite() {}      // 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;                  // Return if asking about ITypeInfo...          if(dwReturnMask & SCRIPTINFO_ITYPEINFO)            return TYPE_E_ELEMENTNOTFOUND;      }            // 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) {      static BSTR pwcErrorText;      pscriptError->GetSourceLineText(&pwcErrorText);      AfxMessageBox(         CString("IActiveScriptSite::OnScriptError()\n") +          CString("Line: ") +          CString(pwcErrorText),         MB_SETFOREGROUND);      ::SysFreeString(pwcErrorText);      return S_OK;   }      virtual HRESULT __stdcall OnEnterScript(void) {      return S_OK;   }      virtual HRESULT __stdcall OnLeaveScript(void) {      return S_OK;   }};// Global instance of our IActiveScriptSite implementation.MyActiveScriptSite g_iActiveScriptSite;// Script Engine CLSIDs...#include 
    DEFINE_GUID(CLSID_VBScript, 0xb54f3741, 0x5b07, 0x11cf, 0xa4, 0xb0, 0x0, 0xaa, 0x0, 0x4a, 0x55, 0xe8);DEFINE_GUID(CLSID_JScript, 0xf414c260, 0x6ac0, 0x11cf, 0xb6, 0xd1, 0x00, 0xaa, 0x00, 0xbb, 0xbb, 0x58);// Ole-initialization class.class OleInitClass {public: OleInitClass() { OleInitialize(NULL); } ~OleInitClass() { OleUninitialize(); }};// This global class calls OleInitialize() at// application startup, and calls OleUninitialize()// at application exit...OleInitClass g_OleInitClass;void HRVERIFY(HRESULT hr, char * msg){ if(FAILED(hr)) { CString str; str.Format("Error: 0x%08lx (%s)", hr, msg); AfxMessageBox(str, 0x10000); _exit(0); }}
  12. 编译并运行。
生成项目后,运行它,向您的应用程序编辑框中,添加下面的 VBScript 然后单击的按钮:
dim x   dim y   dim z   x = 101*199   y = 313*199   z = gcd(x, y)   ShowValue "gcd(" & x & ", " & y & ") = ", z   HelpAbout
基本工作流如下所示:
  1. 首先,VBScript 引擎,vbscript.dll,并获得 IActiveScript 和 IActiveScriptParse 接口。
  2. 您授予的 VBScript 引擎 IActiveScriptSite,引擎使用更高版本来获取,然后对您的对象调用的实现。
  3. 您添加的对象的实现,并希望对脚本可通过调用 IActiveScript::AddNamedItem()。
  4. 您提供的脚本文本通过 IActiveScriptParse::ParseScriptText() 执行。请注意这实际上还不是在运行该脚本。
  5. 脚本引擎将立即连接到您的 IActiveScriptSite::GetItemInfo() 无法识别,若要获取的接口指针的任何对象。
  6. IActiveScript::SetScriptState() 与 SCRIPT_STATE_CONNECTED 以运行该脚本,则调用。
  7. VBScript 引擎分析为您的脚本中的文本,以及当它遇到的方法调用或属性的引用时,它委托给您提供的接口的实现。

<linker : >

<linker : exmaple code : >

转载地址:http://kcevx.baihongyu.com/

你可能感兴趣的文章
C++Premer Plus学习(五)——函数探幽
查看>>
oracle 自动关闭 数据库连接
查看>>
linux达人养成计划学习笔记(一)——命令基本格式及文件处理命令
查看>>
Bamboo简介
查看>>
[Leetcode] Populating Next Right Pointers in Each Node II
查看>>
[LeetCode] Word Ladder
查看>>
C#反射设置属性值和获取属性值
查看>>
iOS运行时编程(Runtime Programming)和Java的反射机制对比
查看>>
数据仓库走向灭亡??
查看>>
MS Big Data Solution
查看>>
Object [object Object] has no method 'live'
查看>>
STL - 判断式(Predicate) - 单参判断式(Unary Predicate)
查看>>
Entity Framework 4 错误
查看>>
xBIM 多个IFC文件合并
查看>>
集成电路中的assert和deassert应该如何翻译?
查看>>
[转载]Java文件路径详解
查看>>
瑞星播报:3月8日需警惕“灰鸽子变种AWM”病毒
查看>>
python操作gmail
查看>>
ChildActionOnly + ActionName的用法
查看>>
log4net 共享访问一个log文件的方法
查看>>