程序中使用VBScript
以下是我从几个例程中总结出的基本方法,其中没有事件的处理功能,如果要源码的话可与我联系(
[email protected])
1.头文件包含
#include
#include
2.在类中声明以下两个成员
IActiveScript *m_pIActiveScript;
IActiveScriptParse *m_pIActiveScriptParse;
3.在CMainFrame类声明中的DECLARE_MESSAGE_MAP()后加上以下代码
DECLARE_INTERFACE_MAP()
BEGIN_INTERFACE_PART(ScriptSite, IActiveScriptSite)
STDMETHOD(GetLCID)(LCID *plcid);
STDMETHOD(GetItemInfo)(LPCOLESTR pstrName, DWORD dwReturnMask, IUnknown **ppiunkItem, ITypeInfo **ppti);
STDMETHOD(GetDocVersionString)(BSTR *pszVersion);
STDMETHOD(RequestItems)(void);
STDMETHOD(RequestTypeLibs)(void);
STDMETHOD(OnScriptTerminate)(const VARIANT *pvarResult, const EXCEPINFO *pexcepinfo);
STDMETHOD(OnStateChange)(SCRIPTSTATE ssScriptState);
STDMETHOD(OnScriptError)(IActiveScriptError *pscripterror);
STDMETHOD(OnEnterScript)(void);
STDMETHOD(OnLeaveScript)(void);
END_INTERFACE_PART(ScriptSite)
BEGIN_INTERFACE_PART(ScriptSiteWindow, IActiveScriptSiteWindow)
STDMETHOD(GetWindow)(HWND *phwnd);
STDMETHOD(EnableModeless)(BOOL fEnable);
END_INTERFACE_PART(ScriptSiteWindow)
/*********************************************
加上以上代码后在CMainFrame类中会多两个成员 m_xScriptSite 与 m_xScriptSiteWindow
**********************************************/
//以下是从上面移下来的
IActiveScript *m_pIActiveScript;
IActiveScriptParse *m_pIActiveScriptParse;
4.实现3中的代码
1)在END_MESSAGE_MAP()后加上以下代码
BEGIN_INTERFACE_MAP(CMainFrame, CFrameWnd)
INTERFACE_PART(CMainFrame, IID_IActiveScriptSite, ScriptSite)
INTERFACE_PART(CMainFrame, IID_IActiveScriptSiteWindow, ScriptSiteWindow)
END_INTERFACE_MAP()
2)实现m_xScriptSite中的成员方法
//COM interface implementation
ULONG FAR EXPORT CMainFrame::XScriptSite::AddRef()
{
METHOD_PROLOGUE(CMainFrame, ScriptSite)
return pThis->ExternalAddRef();
}
ULONG FAR EXPORT CMainFrame::XScriptSite::Release()
{
METHOD_PROLOGUE(CMainFrame, ScriptSite)
return pThis->ExternalRelease();
}
HRESULT FAR EXPORT CMainFrame::XScriptSite::QueryInterface( REFIID iid, void FAR* FAR* ppvObj)
{
METHOD_PROLOGUE(CMainFrame, ScriptSite)
return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
}
ULONG FAR EXPORT CMainFrame::XScriptSiteWindow::AddRef()
{
METHOD_PROLOGUE(CMainFrame, ScriptSiteWindow)
return pThis->ExternalAddRef();
}
ULONG FAR EXPORT CMainFrame::XScriptSiteWindow::Release()
{
METHOD_PROLOGUE(CMainFrame, ScriptSiteWindow)
return pThis->ExternalRelease();
}
HRESULT FAR EXPORT CMainFrame::XScriptSiteWindow::QueryInterface( REFIID iid, void FAR* FAR* ppvObj)
{
METHOD_PROLOGUE(CMainFrame, ScriptSiteWindow)
return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
}
/////////////////////////////////////////////////////////////////////////////
// ActiveScript hosting
// ##### BEGIN ACTIVEX SCRIPTING SUPPORT #####
//***************************************************************************
// IActiveScriptSite Interface
//***************************************************************************
STDMETHODIMP CMainFrame::XScriptSite::GetLCID(LCID *plcid)
{
return E_NOTIMPL; // Use system settings
}
STDMETHODIMP CMainFrame::XScriptSite::GetItemInfo( LPCOLESTR pstrName,
DWORD dwReturnMask,
IUnknown** ppunkItemOut,
ITypeInfo** pptinfoOut )
{
return TYPE_E_ELEMENTNOTFOUND;
}
STDMETHODIMP CMainFrame::XScriptSite::GetDocVersionString(BSTR *pbstrVersion)
{
return E_NOTIMPL; // UNDONE: Implement this method
}
STDMETHODIMP CMainFrame::XScriptSite::RequestItems(void)
{
return E_NOTIMPL;
}
STDMETHODIMP CMainFrame::XScriptSite::RequestTypeLibs(void)
{
METHOD_PROLOGUE(CMainFrame,ScriptSite);
return E_NOTIMPL;
}
STDMETHODIMP CMainFrame::XScriptSite::OnScriptTerminate(const VARIANT *pvarResult,
const EXCEPINFO *pexcepinfo)
{
// UNDONE: Put up error dlg here
return S_OK;
}
STDMETHODIMP CMainFrame::XScriptSite::OnStateChange(SCRIPTSTATE ssScriptState)
{
// Don't care about notification
return S_OK;
}
//---------------------------------------------------------------------------
// Display the error
//---------------------------------------------------------------------------
STDMETHODIMP CMainFrame::XScriptSite::OnScriptError(IActiveScriptError *pse)
{
METHOD_PROLOGUE(CMainFrame,ScriptSite);
CString strError;
CString strArrow;
CString strDesc;
CString strLine;
EXCEPINFO ei;
DWORD dwSrcContext;
ULONG ulLine;
LONG ichError;
BSTR bstrLine = NULL;
HRESULT hr;
pse->GetExceptionInfo(&ei);
pse->GetSourcePosition(&dwSrcContext, &ulLine, &ichError);
hr = pse->GetSourceLineText(&bstrLine);
if (hr)
hr = S_OK; // Ignore this error, there may not be source available
if (!hr)
{
strError=ei.bstrSource;
strDesc=ei.bstrDescription;
strLine=bstrLine;
if (ichError > 0 && ichError < 255)
{
strArrow=CString(_T('-'),ichError);
strArrow.SetAt(ichError-1,_T('v'));
}
CString strErrorCopy=strError;
strError.Format(_T("Source:'%s'\nFile:'%s' Line:%d Char:%ld\nError:%d '%s'\n%s\n%s"),
LPCTSTR(strErrorCopy),
_T("File"),
ulLine,
ichError,
(int)ei.wCode,
LPCTSTR(strDesc),
LPCTSTR(strArrow),
LPCTSTR(strLine));
AfxMessageBox(strError);
}
if (bstrLine)
SysFreeString(bstrLine);
return hr;
}
STDMETHODIMP CMainFrame::XScriptSite::OnEnterScript(void)
{
// No need to do anything
return S_OK;
}
STDMETHODIMP CMainFrame::XScriptSite::OnLeaveScript(void)
{
// No need to do anything
return S_OK;
}
//***************************************************************************
// IActiveScriptSiteWindow Interface
//***************************************************************************
STDMETHODIMP CMainFrame::XScriptSiteWindow::GetWindow(HWND *phwndOut)
{
if (!phwndOut)
return E_INVALIDARG;
METHOD_PROLOGUE(CMainFrame,ScriptSiteWindow);
*phwndOut = pThis->GetSafeHwnd();
return S_OK;
}
STDMETHODIMP CMainFrame::XScriptSiteWindow::EnableModeless(BOOL fEnable)
{
return S_OK;
}
// ##### END ACTIVEX SCRIPTING SUPPORT #####
5.添加两个全局变量
const IID CLSID_VBScript = {0xb54f3741, 0x5b07, 0x11cf, {0xa4, 0xb0, 0x0, 0xaa, 0x0, 0x4a, 0x55, 0xe8 } };
const TCHAR* szItemName=_T("Document");
szItemName 是指在脚本中可以直接创建的对象,例如照上面的值则可以如下使用:
Document.MessageBox "sldfk" 'MessageBox 是Document的方法
如果 szItemName=_T("Document1") 则以上的应写为如下形式:
Document1.MessageBox "sldfk" 'MessageBox 是Document1的方法
6.创建脚本对象
HRESULT CMainFrame::CreateScriptEngine(LPCOLESTR pstrItemName)
{
HRESULT hr;
if (m_pIActiveScript)
return S_FALSE; // Already created it
// Create the ActiveX Scripting Engine
hr = CoCreateInstance( CLSID_VBScript,
NULL,
CLSCTX_INPROC_SERVER,
IID_IActiveScript,
(void **)&m_pIActiveScript);
if (FAILED(hr))
{
return E_FAIL;
}
// Script Engine must support IActiveScriptParse for us to use it
hr = m_pIActiveScript->QueryInterface(IID_IActiveScriptParse, (void **)&m_pIActiveScriptParse);
if (hr)
{
return hr;
}
hr = m_pIActiveScript->SetScriptSite(&m_xScriptSite);
if (hr)
return hr;
// InitNew the object:
hr=m_pIActiveScriptParse->InitNew();
//加入宿主对象名
USES_CONVERSION;
LPCOLESTR lpostrApp = T2COLE(szItemName);
hr=m_pIActiveScript->AddNamedItem(lpostrApp, SCRIPTITEM_ISVISIBLE);
return hr;
}
// ##### END ACTIVEX SCRIPTING SUPPORT #####
调用过程:一般在CMainFrame的OnCreate函数中调用
USES_CONVERSION;
LPCOLESTR lpszT = T2COLE(szItemName);
if(CreateScriptEngine(lpszT)!=S_OK)
AfxMessageBox(_T("Can't load the VBScript Engine."));
7.装入脚本
BOOL CMainFrame::LoadTextFile()
{
CFileDialog dlg(TRUE,
_T("*.txt"),
_T("*.txt"),
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
_T("Text files (*.txt)"));
if(dlg.DoModal()==IDOK)
{
m_strCode.Empty();
TCHAR szBuffer[256];
ifstream ifs(dlg.GetPathName());
while(ifs)
{
ifs.getline(szBuffer,256);
m_strCode+=szBuffer;
m_strCode+=_T("\r\n");
}
// ##### BEGIN ACTIVEX SCRIPTING SUPPORT #####
USES_CONVERSION;
EXCEPINFO ei;
LPCOLESTR lpszCode = T2COLE(LPCTSTR(m_strCode));
HRESULT hr=m_pIActiveScriptParse->ParseScriptText(lpszCode, NULL, NULL, NULL, 0, 0, 0L, NULL, &ei);
// ##### END ACTIVEX SCRIPTING SUPPORT #####
if(hr)
{
AfxMessageBox(_T("Can't compile the program."));
return FALSE;
}
return TRUE;
}
return FALSE;
}
8.运行与停止脚本
m_pIActiveScript->SetScriptState(SCRIPTSTATE_CONNECTED);
m_pIActiveScript->SetScriptState(SCRIPTSTATE_DISCONNECTED);
9.支持脚本宿主
在STDMETHODIMP CMainFrame::XScriptSite::GetItemInfo是得到当前宿主可支持的对象:
LPCOLESTR pstrName 对象名称,如在 5 中定义的const TCHAR* szItemName=_T("Document")
DWORD dwReturnMask
IUnknown** ppunkItemOut
ITypeInfo** pptinfoOut 返回对象
实现代码
STDMETHODIMP CMainFrame::XScriptSite::GetItemInfo( LPCOLESTR pstrName,
DWORD dwReturnMask,
IUnknown** ppunkItemOut,
ITypeInfo** pptinfoOut )
{
METHOD_PROLOGUE(CMainFrame, ScriptSite)
USES_CONVERSION;
LPCTSTR lpstrApplication=szItemName;
if (dwReturnMask & SCRIPTINFO_ITYPEINFO)
{
if (!pptinfoOut)
return E_INVALIDARG;
*pptinfoOut = NULL;
}
if (dwReturnMask & SCRIPTINFO_IUNKNOWN)
{
if (!ppunkItemOut)
return E_INVALIDARG;
*ppunkItemOut = NULL;
LPTSTR lpszName = OLE2T(pstrName);
if(!_tcsicmp(lpstrApplication, lpszName))
{
//在应用类中加入相应的Document类,并在应用的构造函数中初始化为NULL, 再在Document的构造函
//数中初始化为当前Document : theApp.m_pDoc = this ;
*ppunkItemOut = theApp.m_pDoc->GetIDispatch(TRUE);
return S_OK;
}
}
return TYPE_E_ELEMENTNOTFOUND;
}
10.为脚本宿主对象添加方法
在ClassView页面中右击向导自动生成的接口(假设应用程序名是AxHost,则接口是IAxHoxt),选择Add Method,在弹出的对话框中输入方法名,如GetDocumentName.其实现代码在相应的Document类中
11.添加接口对象
从ClassWizard中添加类,基类选择CCmdTarget, 并选中Automation选项,假设这里添加的类名是CMyBox,则会自动生成一个IMyBox的接口
12.访问接口对象
在脚本宿主对象的接口上添加一个生成接口对象的方法,具体同10,方法应返回 LPDISPATCH ,例程如下:
LPDISPATCH CAXHostDoc::GetMyBox()
{
CMyBox* pSprite=(CMyBox*)RUNTIME_CLASS(CMyBox)->CreateObject();
return pSprite->GetIDispatch(FALSE);
}
脚本中的代码如下:
dim w
Document1.MessageBox "sldfk"
Dim MyBox
set MyBox = Document1.GetMyBox
MyBox.MessageBox "这是从MyBox中弹出的消息"
本文地址:http://com.8s8s.com/it/it3711.htm