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

如何添加到 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 <activscp.h> // Include definition for MyScriptObject... #include "MyScriptObject.h"
  11. 将以下代码添加到您 [只是之前的按钮处理程序实现,在 projectname]Dlg.cpp 文件:

    // Your IActiveScriptSite implementation...class MyActiveScriptSite : public IActiveScriptSite { private: ULONG m_dwRef; // Reference count public: 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 <initguid.h> 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 : ​​http://support.microsoft.com/kb/221992/zh-cn​​>

<linker : exmaple code : ​​http://www.pudn.com/downloads70/sourcecode/windows/other/detail251422.html​​>