如何在VC程序中支持脚本程序

kane_yj 2001-05-11 01:04:00
如何在VC程序中支持脚本程序
Script
...全文
151 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
CoolHg 2001-05-11
  • 打赏
  • 举报
回复
MFC程序中使用VBScript与Jscript(二)
(一)你可以到文档中心查找一下,不过不太好看
下面是我写几个类,用于实现脚本功能,你只要把以下几个类加入到你的程序中就可以实现对脚本的支持(还是没有事件支持),如果要源码可与我联系(LiuYangquan@sina.com)

一、头文件
#include <Activscp.h>
#include <AFXPRIV.H>

const IID IID_LIBAXHost=
{ 0x34E2595E, 0x6314, 0x11D1, { 0x8F, 0x0B, 0xF5, 0x41, 0x76, 0xDC, 0xF1, 0x30 } };

/**************************************************************************
当Script Host 程序需要实现用户界面时(指调用Script的MsgBox等用户响应的函数时)需要实现 IActiveScriptSiteWindow 接口,其中的 CWnd* 即是 MsgBox 弹出窗口的父窗口,需要在 GetWindow 中返回
**************************************************************************/
class CuScriptSiteWindow : public IActiveScriptSiteWindow
{
public:
CuScriptSiteWindow()
{
m_ref = 1;
m_pWnd = NULL ;
}
STDMETHODIMP GetWindow(HWND *phwnd);
STDMETHODIMP EnableModeless(BOOL fEnable);
virtual ULONG __stdcall AddRef();
virtual ULONG __stdcall Release();
virtual HRESULT _stdcall QueryInterface(REFIID riid, void **ppvObject);

public:
HWND m_pWnd;
protected:
ULONG m_ref;
};

/**************************************************************************
任何 Script Host 程序必须提供一个实现了 IActiveScriptSite 的接口的类
**************************************************************************/

class CuActiveScriptSite : public IActiveScriptSite
{
public:
CuActiveScriptSite::CuActiveScriptSite()
{m_dwRef = 1;}
CuActiveScriptSite::~CuActiveScriptSite()
{}

virtual HRESULT _stdcall QueryInterface(REFIID riid, void **ppvObject);
virtual ULONG _stdcall AddRef(void);
virtual ULONG _stdcall Release(void);
virtual HRESULT _stdcall GetLCID(LCID *plcid) ;
virtual HRESULT _stdcall GetItemInfo( LPCOLESTR pstrName,
DWORD dwReturnMask,
IUnknown **ppunkItem,
ITypeInfo **ppti);
virtual HRESULT __stdcall OnScriptError(IActiveScriptError *pse) ;
virtual HRESULT __stdcall GetDocVersionString(BSTR *pbstrVersion) ;
virtual HRESULT __stdcall OnScriptTerminate( const VARIANT *pvarResult,
const EXCEPINFO *pexcepInfo) ;
virtual HRESULT __stdcall OnStateChange(SCRIPTSTATE ssScriptState) ;
virtual HRESULT __stdcall OnEnterScript(void) ;
virtual HRESULT __stdcall OnLeaveScript(void) ;

public:
//脚本宿主对象名
LPCOLESTR m_CuObjectName;

// 指向 GetItemInfo 中返回的对象名,
//用于在脚本中直接以脚本对象名调用对象的对象
IUnknown *m_pUnkScriptObject;

//用于运行诸如MsgBox等VBS中的用户界面的函数
CuScriptSiteWindow m_xScriptSiteWindow;
protected:
ULONG m_dwRef;
};


/***************************************************************************
脚本引擎辅助类,用于创建脚本引擎
****************************************************************************/
class CScriptEngine
{
public:
CScriptEngine();
virtual ~CScriptEngine();
HRESULT CreateEngine( LPCOLESTR pstrItemName, //脚本宿主对象名
CCmdTarget* pTagObj=NULL, //脚本宿主对象
HWND pScriptParentWnd=NULL //脚本交互界面父窗口
);
public:
BOOL Run();
Stop();
void SetScript( CString strScript );
CString m_strScript;
IActiveScript *m_pIActiveScript;
IActiveScriptParse *m_pIActiveScriptParse;
CuActiveScriptSite m_xScriptSite;
CCmdTarget* m_ScriptObject;
};

二、实现文件
const IID CLSID_VBScript = {0xb54f3741, 0x5b07, 0x11cf, {0xa4, 0xb0, 0x0, 0xaa, 0x0, 0x4a, 0x55, 0xe8 } };

/*******************************************
****Begin the ScriptSiteWindow Implents*****
********************************************/

ULONG __stdcall CuScriptSiteWindow::AddRef()
{
m_ref++;
return m_ref;
}

ULONG __stdcall CuScriptSiteWindow::Release()
{
m_ref--;
return m_ref;
}

// 得到用户界面的主窗口
STDMETHODIMP CuScriptSiteWindow::GetWindow(HWND *phwnd)
{
if( NULL == m_pWnd )
return E_INVALIDARG;
*phwnd = m_pWnd;
return S_OK;
}

STDMETHODIMP CuScriptSiteWindow::EnableModeless(BOOL fEnable)
{
return S_OK;
}
HRESULT _stdcall CuScriptSiteWindow::QueryInterface(REFIID riid, void **ppvObject)
{
if( riid == IID_IActiveScriptSiteWindow )
*ppvObject = this;
else
*ppvObject = NULL;
return S_OK;
}

/*******************************************
****End the ScriptSiteWindow Implents*****
********************************************/

/*******************************************
****Begin the ScriptSite Implents*****
********************************************/

ULONG _stdcall CuActiveScriptSite::AddRef(void)
{
return ++m_dwRef;
}
ULONG _stdcall CuActiveScriptSite::Release(void)
{
if(--m_dwRef <= 0) return 0;
return m_dwRef;
}
HRESULT _stdcall CuActiveScriptSite::QueryInterface(REFIID riid, void **ppvObject)
{
if( riid == IID_IActiveScriptSiteWindow )
{
*ppvObject = &m_xScriptSiteWindow;
return S_OK;
}
*ppvObject = NULL;
return E_NOTIMPL;
}
HRESULT _stdcall CuActiveScriptSite::GetLCID(LCID *plcid)
{
return E_NOTIMPL;
}
HRESULT __stdcall CuActiveScriptSite::GetDocVersionString(BSTR *pbstrVersion)
{
return S_OK;
}
HRESULT _stdcall CuActiveScriptSite::GetItemInfo( LPCOLESTR pstrName,
DWORD dwReturnMask,
IUnknown **ppunkItem,
ITypeInfo **ppti)
{

USES_CONVERSION;

if (dwReturnMask & SCRIPTINFO_ITYPEINFO)
{
if (!ppti)
return E_INVALIDARG;
*ppti = NULL;
}
if(ppunkItem)
{
if( NULL==m_pUnkScriptObject )
{
*ppunkItem = NULL;
return E_INVALIDARG;
}else
{
if (dwReturnMask & SCRIPTINFO_IUNKNOWN)
{
if(!_wcsicmp(m_CuObjectName, pstrName))
{
*ppunkItem = m_pUnkScriptObject;
// Addref our object...
m_pUnkScriptObject->AddRef();
return S_OK;
}
}
}
}

return S_OK; //TYPE_E_ELEMENTNOTFOUND;
}


HRESULT __stdcall CuActiveScriptSite::OnScriptTerminate( const VARIANT *pvarResult,
const EXCEPINFO *pexcepInfo)
{
return S_OK;
}

HRESULT __stdcall CuActiveScriptSite::OnStateChange(SCRIPTSTATE ssScriptState)
{
return S_OK;
}

HRESULT __stdcall CuActiveScriptSite::OnEnterScript(void)
{
return S_OK;
}

HRESULT __stdcall CuActiveScriptSite::OnLeaveScript(void)
{
return S_OK;
}

HRESULT __stdcall CuActiveScriptSite::OnScriptError(IActiveScriptError *pse)
{
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;
}



CScriptEngine::CScriptEngine()
{
OleInitialize(NULL);
this->m_pIActiveScript = NULL;
this->m_pIActiveScriptParse = NULL ;
this->m_ScriptObject = NULL ;
}

CScriptEngine::~CScriptEngine()
{
if( m_pIActiveScriptParse!=NULL )
{
m_pIActiveScriptParse->Release();
}
if( m_pIActiveScriptParse!=NULL )
{
m_pIActiveScript->Close();
m_pIActiveScript->Release();
}
OleUninitialize();

}



HRESULT CScriptEngine::CreateEngine(LPCOLESTR pstrItemName, CCmdTarget* pTagObj, HWND pScriptParentWnd)
{
HRESULT hr;

if (m_pIActiveScript!=NULL)
return S_FALSE; // Already created it
m_xScriptSite.m_pUnkScriptObject = NULL;

m_ScriptObject = pTagObj;

this->m_xScriptSite.m_xScriptSiteWindow.m_pWnd =pScriptParentWnd;

if( NULL!=m_ScriptObject )
{
this->m_xScriptSite.m_pUnkScriptObject = m_ScriptObject->GetInterface( &IID_IUnknown );
if( NULL==m_xScriptSite.m_pUnkScriptObject )
{
_exit(0);
}
}else
{
this->m_xScriptSite.m_pUnkScriptObject = NULL;
}

hr = CoCreateInstance( CLSID_VBScript,
NULL,
CLSCTX_INPROC_SERVER,
IID_IActiveScript,
(void **)&this->m_pIActiveScript );
if( FAILED(hr) )
return hr;

hr = m_pIActiveScript->QueryInterface( IID_IActiveScriptParse,
(void **)&this->m_pIActiveScriptParse);
if( FAILED(hr) )
return hr;

m_xScriptSite.m_CuObjectName = pstrItemName;

hr = m_pIActiveScript->SetScriptSite(&this->m_xScriptSite);

if( FAILED(hr) )
return hr;

hr = m_pIActiveScriptParse->InitNew();
if( FAILED(hr) )
return hr;

hr = m_pIActiveScript->AddNamedItem(pstrItemName, SCRIPTITEM_ISVISIBLE | SCRIPTITEM_ISSOURCE);

if( FAILED(hr) )
return hr;
return hr;


}



void CScriptEngine::SetScript(CString strScript)
{
Stop();
m_strScript = strScript ;

this->m_pIActiveScriptParse->InitNew();

USES_CONVERSION;
EXCEPINFO ei;
LPCOLESTR lpszCode = T2COLE(LPCTSTR(m_strScript));
HRESULT hr=m_pIActiveScriptParse->ParseScriptText( lpszCode,
NULL, //L"MyObject", //NULL,
NULL,
NULL,
0, 0, 0L,
NULL, &ei);

if(FAILED(hr))
{
AfxMessageBox(_T("Can't compile the program."));
// return FALSE;
}
}

CScriptEngine::Stop()
{
m_pIActiveScript->SetScriptState(SCRIPTSTATE_DISCONNECTED);
}

BOOL CScriptEngine::Run()
{
if( m_strScript.IsEmpty() )
return FALSE;
if(m_pIActiveScript->SetScriptState(SCRIPTSTATE_CONNECTED))
{
AfxMessageBox(_T("Can't run the program."));
return FALSE;
}

return TRUE;
}


HRESULT InvokeEvent( IDispatch *pdisp, // IDispatch of Sink
DISPID dispid, // DISPID of event
VARIANTARG *pvararg, // Args to event
UINT carg // # args
)
{
DISPPARAMS dp;
EXCEPINFO ei;
UINT uArgErr = 0;

dp.rgvarg = pvararg;
dp.rgdispidNamedArgs = NULL;
dp.cArgs = carg;
dp.cNamedArgs = 0;
return pdisp->Invoke(dispid, IID_NULL, 0, DISPATCH_METHOD, &dp, NULL, &ei, &uArgErr);
}

三、 使用方法
1.添加脚本宿主对象
1).从CcmdTarget派生一类(假设是CScriptObject),并选择Automation 选项
2).在类定义的最后加上下面两句
DECLARE_DISPATCH_MAP()
DECLARE_INTERFACE_MAP()
3).在类实现文件的头部 END_MESSAGE_MAP() 后加上
BEGIN_DISPATCH_MAP(CScriptObject, CCmdTarget)
//{{AFX_DISPATCH_MAP(CScriptObject)
//}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()

static const IID IID_IScriptObject =
{ 0x64d225b1, 0x761b, 0x4414, { 0xba, 0x77, 0x98, 0x27, 0xc3, 0xf1, 0xc6, 0x30 } };
//由Guid获得
BEGIN_INTERFACE_MAP(CScriptObject, CCmdTarget)
INTERFACE_PART(CScriptObject, IID_IScriptObject, Dispatch)
END_INTERFACE_MAP()
4).添加脚本宿主对象方法(假设是 CreateObject )
(1) 按照常规方法为类添加一个成员函数,成员函数的参数与返回值应是标准数据或OLE的标准数据
LPDISPATCH CScriptObject::CreateDrawObject()
{
return g_obj.GetIDispatch( TRUE );
}
b_obj 也是一个实现了 Automation 的 CcmdTarget 的子类实例
(2) 引出脚本宿主对象的方法

BEGIN_DISPATCH_MAP(CScriptObject, CCmdTarget)
//{{AFX_DISPATCH_MAP(CScriptObject)
//}}AFX_DISPATCH_MAP
END_DISPATCH_MAP()
之间的 AFX_DISPATCH_MAP 中间加上
DISP_FUNCTION(CScriptObject, "CreateObject", CreateObject, VT_DISPATCH, VTS_NONE)

(3) 定义一个 CscriptObject 的全局变量 g_ScriptObject
(4) 按照上面的方法再定义一个类,其主要是用于测试 CreateoBject 方法,添加 SetFileName 方法,并定义一个全局变量
(5) 创建脚本引擎
为 CMainFrame 或 Dlg 定义一个 CScriptEngine成员
在 CMainfFrame 或 Dlg 类的 OnCreate 函数中调用 CscriptEngine 的CreateEngine 创建脚本引擎
i) 支持用户界面与脚本宿主对象
Createengine( L”Document”, &g_ScriptObject, this->GetSafeHwnd() );
脚本例子
MsgBox “这个脚本支持用户界面”
Dim Obj
set obj=Document.CreateObject
obj.SetFileName "c:\hdc.txt"
ii)支持脚本对象,但不支持用户界面
Createengine( L”Document”, &g_ScriptObject, NULL );
脚本例子
MsgBox “这个脚本支持用户界面” ‘调用时会出现无权限的错误
Dim Obj
set obj=Document.CreateObject
obj.SetFileName "c:\hdc.txt"

iii)支持用户界面不支持脚本宿主对象
Createengine( L”Document”, NULL, this->GetSafeHwnd() );
脚本例子
MsgBox “这个脚本支持用户界面”
Dim Obj
set obj=Document.CreateObject
‘调用时会出现在( '无效的过程调用或参数: 'Document'' )的错误
obj.SetFileName "c:\hdc.txt"

iv)两者都不支持
Createengine( L”Document”, NULL, NULL );
基本没什么意义
用 SetScript 设置脚本
用 Run 运行脚本
用 Stop 停止脚

supperlxf 2001-05-11
  • 打赏
  • 举报
回复
用ie控件 用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件用ie控件
kane_yj 2001-05-11
  • 打赏
  • 举报
回复
先谢了!
kane_yj 2001-05-11
  • 打赏
  • 举报
回复
to:
Kevin_qing(Kevin) 
先谢了!
singlerace 2001-05-11
  • 打赏
  • 举报
回复
自己做语法分析,执行。
Kevin_qing 2001-05-11
  • 打赏
  • 举报
回复
给你点资料吧
http://www.gpgame.com/docs/program/script.zip
kane_yj 2001-05-11
  • 打赏
  • 举报
回复
高手................
kane_yj 2001-05-11
  • 打赏
  • 举报
回复
??????

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧