如何在vc程序中嵌入脚本语言初稿.docx

上传人:b****8 文档编号:9983613 上传时间:2023-02-07 格式:DOCX 页数:13 大小:144.35KB
下载 相关 举报
如何在vc程序中嵌入脚本语言初稿.docx_第1页
第1页 / 共13页
如何在vc程序中嵌入脚本语言初稿.docx_第2页
第2页 / 共13页
如何在vc程序中嵌入脚本语言初稿.docx_第3页
第3页 / 共13页
如何在vc程序中嵌入脚本语言初稿.docx_第4页
第4页 / 共13页
如何在vc程序中嵌入脚本语言初稿.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

如何在vc程序中嵌入脚本语言初稿.docx

《如何在vc程序中嵌入脚本语言初稿.docx》由会员分享,可在线阅读,更多相关《如何在vc程序中嵌入脚本语言初稿.docx(13页珍藏版)》请在冰豆网上搜索。

如何在vc程序中嵌入脚本语言初稿.docx

如何在vc程序中嵌入脚本语言初稿

如何在vc程序中嵌入脚本语言

今天很多大型程序中都能够见到内嵌脚本进行二次开发的功能,例如msword,excel,visualstudio等。

一直以来我都希望能在自己的程序中加入同样的功能,经过前一段时间的研究,终于有所心得与大家分享。

在研究过程中,我查找了发现一篇比较有价值的文章(

其原理如下

1.首先使用CoCreateInstance()创建某种脚本语言(javascript,vbscript)的引擎,获得某种语言的脚本引擎的接口IActiveScript。

2.实现回调站点接口IActiveScriptSite通过IActiveScript->SetScriptSite()交由脚本引擎回调,在site中可以取得引擎的状态信息,并提供用户的自定义变量的自动化对象。

3.通过IActiveScript->QueryInterface()取得IActiveScriptParse接口,IActiveScriptParse用于解释执行用户的脚本代码。

幸运的是这一系列接口和操作已经被文章的作者封装成CActiveScriptHost类,只需要掌握CreateEngine()(创建脚本引擎),AddScriptCode()(加入用户脚本代码),AddScriptItem()(加入用户自定义变量)四个常用的方法即可。

下面描述如何在自己mfc程序中使用上述类嵌入脚本和自定义脚本对象的过程,步骤如下。

1.首先将文章所附例子工程中ActiveScriptHost.cpp,ActiveScriptHost.h,Host_Proxy.cpp,Host_Proxy.h,MFCScriptHost.odl拷贝到当前工程中。

2.在当前工程的xxx.rc中加入以下内容,即将类型库加入到程序资源文件中

#ifdef_DEBUG

1TYPELIB"Debug\\MFCScriptHost.tlb"

#else

1TYPELIB"Release\\MFCScriptHost.tlb"

#endif

3.在需要使用的类成员中加入CHost_Proxym_ScriptProxy;成员,在OnCreate或OnInitDialog中加入

m_ScriptProxy.CreateEngine(L"JavaScript");//创建脚本引擎

m_ScriptProxy.AddScriptItem(L"test",m_ptestObject->GetUnknown());//加入名称为test的IDispatch对象

4.

com对象的生成有两种方案,一种是使用MFC方式生成,即对象从CmdTarget继承,并选中automation的radiobutton(如图表1),并通过ClassWizard中的自动化标签加入方法和属性(如图表2)。

这种对象的缺点是无法自定义事件源供脚本程序接收。

图表1

图表2

5.

另一种是使用ATL产生com对象,这种方式可以生成带事件功能的对象,此外功能灵活、方便。

我更倾向于ATL方式生成com对象。

在Classes点击右键选择NewATLObject(如图表3),出现ATLObjectWizard(如图表4)。

选中SimpleObject,出现ATLObjectWizard属性对话框(如图表5),按要求填入shortname(即组件名称),如果欲支持组件的事件功能一定选中SupportConnectionPoints(如图表6),点击确定后vc会自动生成代码。

图表3

图表4

图表5

图表6

6.在vc生成的InitATL()后,一定要手工加入_Module.RegisterTypeLib()用来注册组件的类型库。

这是因为TL的IDispatch实现会将自身调用委托给相应组件的类型库接口ITypeInfo去执行(如图表7)。

图表7

7.如欲实现组件的事件功能还需在相应对象点击ImplementConnectionPoint菜单项(如图表8),选择实现事件源接口(如图表9),点击确定后系统会生成发送出发事件的委托类,并添加相应代码(如图表10)。

图表8

图表9

图表10

8.

因为com对象发出的事件需要在脚本环境下使用,脚本环境需要通过对象的IProvideClassInfo2接口获得默认事件源(即sourcedefaultdispinterface),所以com对象还需实现IProvideClassInfo2接口(如图表11),加入红框内内容即可。

图表11

9.脚本内调用的codesample例子如下,假设对象test有方法hello,有事件OnRun()

javaScript例子

test.hello()//调用test对象的hello方法

functiontest:

:

OnRun()//test对象事件OnRun()的回调函数

{

}

vbScript例子

test.hello‘调用test对象的hello方法

Subtest_OnRun()‘test对象事件OnRun()的回调函数

endSub

Jscript与VbScript详细用法见

msdn/platformSDKdocumentation/ToolsandScripting/Scripting

10.如果使用mfc方式生成的com对象,用以下代码将对象作为脚本变量加入到脚本环境中

m_ScriptProxy.AddScriptItem(L"testctrl",m_ctrl.GetIDispatch(FALSE));

11.如果使用ATL方式生成的com对象,用以下代码将对象作为脚本变量加入到脚本环境中

CComObject:

:

CreateInstance(&m_peventObject);

//因为多步骤构造需要调用finalContruct

m_ScriptProxy.AddScriptItem(L"event",m_peventObject->GetUnknown());

12.脚本代码的接入方法,strScriptText为代码脚本

CStringstrScriptText;

m_ctlScriptText.GetWindowText(strScriptText);

if(strScriptText.GetLength()>0)

{

BSTRbstrText=strScriptText.AllocSysString();

m_ScriptProxy.AddScriptCode(bstrText);

SysFreeString(bstrText);

}

下面简要介绍将一个MFC的CButton变为脚本中可用组件的方法

用上述步骤建立CAtlButton,CAtlRect

classATL_NO_VTABLECAtlButton:

publicCComObjectRootEx,

publicCComCoClass,

publicIConnectionPointContainerImpl,

publicIDispatchImpl

{

//IAtlButton

public:

STDMETHOD(Move)(/*[in]*/IAtlRect*rect);//移动button

STDMETHOD(get_Rect)(/*[out,retval]*/IAtlRect**pVal);//得到buttonsize

};

classATL_NO_VTABLECAtlRect:

publicCComObjectRootEx,

publicCComCoClass,

publicIDispatchImpl

{

public:

CRectm_rc;

public:

STDMETHOD(get_Bottom)(/*[out,retval]*/long*pVal);

STDMETHOD(put_Bottom)(/*[in]*/longnewVal);

STDMETHOD(get_Right)(/*[out,retval]*/long*pVal);

STDMETHOD(put_Right)(/*[in]*/longnewVal);

STDMETHOD(get_Left)(/*[out,retval]*/long*pVal);

STDMETHOD(put_Left)(/*[in]*/longnewVal);

STDMETHOD(get_Top)(/*[out,retval]*/long*pVal);

STDMETHOD(put_Top)(/*[in]*/longnewVal);

};

classCButtonWithAtl:

publicCButton,publicCComObjectGlobal

{

public:

STDMETHOD(get_Rect)(/*[out,retval]*/IAtlRect**pVal);

STDMETHOD(Move)(/*[in]*/IAtlRect*rect);

};

CComObjectGlobal表示com对象全局生存不需要引用计数,CComObject表示在堆上创建对象,通过引用计数控制生命周期。

STDMETHODIMPCButtonWithAtl:

:

get_Rect(IAtlRect**pVal)

{

CRectrc;

this->GetWindowRect(rc);

this->GetParent()->ScreenToClient(rc);

CComObject*pRect;

CComObject:

:

CreateInstance(&pRect);

pRect->m_rc=rc;

pRect->QueryInterface(pVal);

returnS_OK;

}

STDMETHODIMPCButtonWithAtl:

:

Move(IAtlRect*rect)

{

CRectrc;

CComPtrptr(rect);

ptr->get_Left(&rc.left);

ptr->get_Top(&rc.top);

ptr->get_Right(&rc.right);

ptr->get_Bottom(&rc.bottom);

this->MoveWindow(rc);

returnS_OK;

}

加入代码

CButtonWithAtlm_btnRun;

m_ScriptProxy.AddScriptItem(L"runbtn",m_btnRun.GetUnknown());

javaScripttestcode为

varrc=runbtn.Rect;

rc.right+=10;//按钮宽度每次增加10pixel

runbtn.Move(rc);

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 农林牧渔 > 林学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1