您可以添加类似于 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 的活动脚本主机
回到顶端