45fan.com - 路饭网

搜索: 您的位置主页 > 电脑频道 > 电脑教程 > 阅读资讯:实现用于脚本的IDispatch的方法

实现用于脚本的IDispatch的方法

2016-09-01 18:16:39 来源:www.45fan.com 【

实现用于脚本的IDispatch的方法

做这个Dispatch实现基类的目标有3个:

1。能够很方便滴映射成员供脚本(包括使用WebBrowser的external对象)访问;

2。最好能不依赖MFC;

3。不用tlb文件,不写注册表。

实现的时候,参考了Delphi的ComAutoObj(话说回来,这个单元的BUG可不小,上次做的时候用着用着就出错。。。还好有个好心的澳大利亚青年发了个补丁……扯到哪里去了-___-b) 最后完成下来,派生类中的映射是这样滴,看起来还不错:P,也没有像MFC的CDispatchHelper里面的VTS_I4这样的东东了:

BEGIN_AC_DISPMAP(CMyGlobal)
AC_DISP_FUNCTION(1, L"alert", alert)
AC_DISP_FUNCTION(2, L"add", add2)
AC_DISP_PROP(3, L"count", get_count, put_count)
AC_DISP_READONLYPROP(4, L"beeper", get_beeper)
END_AC_DISPMAP()

不多说鸟,贴CODE:

ACDispatch.h

#pragma once

#include "oaidl.h"
#include "comutil.h"

#define BEGIN_AC_DISPMAP(theClass)/
typedef void (theClass::*_AC_DispP1Func)(_variant_t, _variant_t&);/
HRESULT MultiParamInvoke(_AC_DispP1Func func, DISPPARAMS *pDispParams, VARIANT *pVarResult)/
{/
if ( pDispParams->cArgs != 1 ) return E_INVALIDARG;/
_variant_t v1(pDispParams->rgvarg[0]);/
_variant_t retval;/
(this->*func)(v1, retval);/
if (pVarResult) *pVarResult = retval;/
return S_OK;/
}/
typedef void (theClass::*_AC_DispP2Func)(_variant_t, _variant_t, _variant_t&);/
HRESULT MultiParamInvoke(_AC_DispP2Func func, DISPPARAMS *pDispParams, VARIANT *pVarResult)/
{/
if ( pDispParams->cArgs != 2 ) return E_INVALIDARG;/
_variant_t v1(pDispParams->rgvarg[0]);/
_variant_t v2(pDispParams->rgvarg[1]);/
_variant_t retval;/
(this->*func)(v1, v2, retval);/
if (pVarResult) *pVarResult = retval;/
return S_OK;/
}/
typedef void (theClass::*_AC_DispP3Func)(_variant_t, _variant_t, _variant_t, _variant_t&);/
HRESULT MultiParamInvoke(_AC_DispP3Func func, DISPPARAMS *pDispParams, VARIANT *pVarResult)/
{/
if ( pDispParams->cArgs != 3 ) return E_INVALIDARG;/
_variant_t v1(pDispParams->rgvarg[0]);/
_variant_t v2(pDispParams->rgvarg[1]);/
_variant_t v3(pDispParams->rgvarg[2]);/
_variant_t retval;/
(this->*func)(v1, v2, v3, retval);/
if (pVarResult) *pVarResult = retval;/
return S_OK;/
}/
typedef void (theClass::*_AC_DispP4Func)(_variant_t, _variant_t, _variant_t, _variant_t, _variant_t&);/
HRESULT MultiParamInvoke(_AC_DispP4Func func, DISPPARAMS *pDispParams, VARIANT *pVarResult)/
{/
if ( pDispParams->cArgs != 4 ) return E_INVALIDARG;/
_variant_t v1(pDispParams->rgvarg[0]);/
_variant_t v2(pDispParams->rgvarg[1]);/
_variant_t v3(pDispParams->rgvarg[2]);/
_variant_t v4(pDispParams->rgvarg[3]);/
_variant_t retval;/
(this->*func)(v1, v2, v3, v4, retval);/
if (pVarResult) *pVarResult = retval;/
return S_OK;/
}/
typedef void (theClass::*_AC_DispP5Func)(_variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t&);/
HRESULT MultiParamInvoke(_AC_DispP5Func func, DISPPARAMS *pDispParams, VARIANT *pVarResult)/
{/
if ( pDispParams->cArgs != 5 ) return E_INVALIDARG;/
_variant_t v1(pDispParams->rgvarg[0]);/
_variant_t v2(pDispParams->rgvarg[1]);/
_variant_t v3(pDispParams->rgvarg[2]);/
_variant_t v4(pDispParams->rgvarg[3]);/
_variant_t v5(pDispParams->rgvarg[4]);/
_variant_t retval;/
(this->*func)(v1, v2, v3, v4, v5, retval);/
if (pVarResult) *pVarResult = retval;/
return S_OK;/
}/
typedef void (theClass::*_AC_DispP6Func)(_variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t&);/
HRESULT MultiParamInvoke(_AC_DispP6Func func, DISPPARAMS *pDispParams, VARIANT *pVarResult)/
{/
if ( pDispParams->cArgs != 6 ) return E_INVALIDARG;/
_variant_t v1(pDispParams->rgvarg[0]);/
_variant_t v2(pDispParams->rgvarg[1]);/
_variant_t v3(pDispParams->rgvarg[2]);/
_variant_t v4(pDispParams->rgvarg[3]);/
_variant_t v5(pDispParams->rgvarg[4]);/
_variant_t v6(pDispParams->rgvarg[5]);/
_variant_t retval;/
(this->*func)(v1, v2, v3, v4, v5, v6, retval);/
if (pVarResult) *pVarResult = retval;/
return S_OK;/
}/
typedef void (theClass::*_AC_DispP7Func)(_variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t&);/
HRESULT MultiParamInvoke(_AC_DispP7Func func, DISPPARAMS *pDispParams, VARIANT *pVarResult)/
{/
if ( pDispParams->cArgs != 7 ) return E_INVALIDARG;/
_variant_t v1(pDispParams->rgvarg[0]);/
_variant_t v2(pDispParams->rgvarg[1]);/
_variant_t v3(pDispParams->rgvarg[2]);/
_variant_t v4(pDispParams->rgvarg[3]);/
_variant_t v5(pDispParams->rgvarg[4]);/
_variant_t v6(pDispParams->rgvarg[5]);/
_variant_t v7(pDispParams->rgvarg[6]);/
_variant_t retval;/
(this->*func)(v1, v2, v3, v4, v5, v6, v7, retval);/
if (pVarResult) *pVarResult = retval;/
return S_OK;/
}/
typedef void (theClass::*_AC_DispP8Func)(_variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t&);/
HRESULT MultiParamInvoke(_AC_DispP8Func func, DISPPARAMS *pDispParams, VARIANT *pVarResult)/
{/
if ( pDispParams->cArgs != 8 ) return E_INVALIDARG;/
_variant_t v1(pDispParams->rgvarg[0]);/
_variant_t v2(pDispParams->rgvarg[1]);/
_variant_t v3(pDispParams->rgvarg[2]);/
_variant_t v4(pDispParams->rgvarg[3]);/
_variant_t v5(pDispParams->rgvarg[4]);/
_variant_t v6(pDispParams->rgvarg[5]);/
_variant_t v7(pDispParams->rgvarg[6]);/
_variant_t v8(pDispParams->rgvarg[7]);/
_variant_t retval;/
(this->*func)(v1, v2, v3, v4, v5, v6, v7, v8, retval);/
if (pVarResult) *pVarResult = retval;/
return S_OK;/
}/
typedef void (theClass::*_AC_DispP9Func)(_variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t&);/
HRESULT MultiParamInvoke(_AC_DispP9Func func, DISPPARAMS *pDispParams, VARIANT *pVarResult)/
{/
if ( pDispParams->cArgs != 9 ) return E_INVALIDARG;/
_variant_t v1(pDispParams->rgvarg[0]);/
_variant_t v2(pDispParams->rgvarg[1]);/
_variant_t v3(pDispParams->rgvarg[2]);/
_variant_t v4(pDispParams->rgvarg[3]);/
_variant_t v5(pDispParams->rgvarg[4]);/
_variant_t v6(pDispParams->rgvarg[5]);/
_variant_t v7(pDispParams->rgvarg[6]);/
_variant_t v8(pDispParams->rgvarg[7]);/
_variant_t v9(pDispParams->rgvarg[8]);/
_variant_t retval;/
(this->*func)(v1, v2, v3, v4, v5, v6, v7, v8, v9, retval);/
if (pVarResult) *pVarResult = retval;/
return S_OK;/
}/
typedef void (theClass::*_AC_DispP10Func)(_variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t, _variant_t&);/
HRESULT MultiParamInvoke(_AC_DispP10Func func, DISPPARAMS *pDispParams, VARIANT *pVarResult)/
{/
if ( pDispParams->cArgs != 10 ) return E_INVALIDARG;/
_variant_t v1(pDispParams->rgvarg[0]);/
_variant_t v2(pDispParams->rgvarg[1]);/
_variant_t v3(pDispParams->rgvarg[2]);/
_variant_t v4(pDispParams->rgvarg[3]);/
_variant_t v5(pDispParams->rgvarg[4]);/
_variant_t v6(pDispParams->rgvarg[5]);/
_variant_t v7(pDispParams->rgvarg[6]);/
_variant_t v8(pDispParams->rgvarg[7]);/
_variant_t v9(pDispParams->rgvarg[8]);/
_variant_t v10(pDispParams->rgvarg[9]);/
_variant_t retval;/
(this->*func)(v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, retval);/
if (pVarResult) *pVarResult = retval;/
return S_OK;/
}/
virtual HRESULT GetIDOrInvoke(BOOL bGetID, WORD wFlags, LPOLESTR szName, DISPPARAMS *pDispParams, VARIANT *pVarResult, DISPID* rgDispID)/
{/


#define END_AC_DISPMAP()/
return E_NOTIMPL;/
}


#define AC_DISP_FUNCTION(id, funcName, funcptr)/
if ( bGetID && wcscmp(szName, funcName) == 0 )/
{/
*rgDispID = id;/
return S_OK; /
}/
else if ( (!bGetID) && *rgDispID == id ) /
{ /
return MultiParamInvoke(funcptr, pDispParams, pVarResult);/
}

#define AC_DISP_PROP(id, propName, getfunc, putfunc) /
if ( bGetID && wcscmp(szName, propName) == 0 )/
{/
*rgDispID = id;/
return S_OK;/
}/
else if ( (!bGetID) && *rgDispID == id ) /
{ /
if ( wFlags & (INVOKE_PROPERTYPUT | INVOKE_PROPERTYPUTREF) ) /
{ /
if ( pDispParams->cNamedArgs != 1 || pDispParams->rgdispidNamedArgs[0] != DISPID_PROPERTYPUT ) return DISP_E_MEMBERNOTFOUND; /
putfunc(_variant_t(pDispParams->rgvarg[0]));/
return S_OK; /
} /
else /
{ /
if ( pDispParams->cArgs != 0 ) return DISP_E_BADPARAMCOUNT; /
_variant_t retval; /
getfunc(retval); /
*pVarResult = retval; /
return S_OK; /
} /
}

#define AC_DISP_READONLYPROP(id, propName, getfunc) /
if ( bGetID && wcscmp(szName, propName) == 0 )/
{/
*rgDispID = id;/
return S_OK;/
}/
else if ( (!bGetID) && *rgDispID == id ) /
{ /
if ( pDispParams->cArgs != 0 ) return DISP_E_BADPARAMCOUNT; /
_variant_t retval; /
getfunc(retval); /
*pVarResult = retval; /
return S_OK; /
} /

/********************** 广告位招租 *************************/

/*
*CACAutoDispatch : a simple dispatch driver used for script
*/
class CACAutoDispatch : public IDispatch
{
private:
UINTm_uRefCount;
public:
CACAutoDispatch(BOOL bZeroRefCount);
virtual ~CACAutoDispatch(void);
public:
virtual HRESULT STDMETHODCALLTYPE QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ void ** ppvObject);

virtual ULONG STDMETHODCALLTYPE AddRef(void);

virtual ULONG STDMETHODCALLTYPE Release(void);

virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(
/* [out] */ UINT *pctinfo);

virtual HRESULT STDMETHODCALLTYPE GetTypeInfo(
/* [in] */ UINT iTInfo,
/* [in] */ LCID lcid,
/* [out] */ ITypeInfo **ppTInfo);

virtual HRESULT GetIDOrInvoke(BOOL bGetID, WORD wFlags, LPOLESTR szName, DISPPARAMS *pDispParams, VARIANT *pVarResult, DISPID* rgDispID) = 0;

virtual HRESULT STDMETHODCALLTYPE GetIDsOfNames(
/* [in] */ REFIID riid,
/* [size_is][in] */ LPOLESTR *rgszNames,
/* [in] */ UINT cNames,
/* [in] */ LCID lcid,
/* [size_is][out] */ DISPID *rgDispId)
{
return GetIDOrInvoke(TRUE, 0, rgszNames[0], NULL, NULL, rgDispId);
}

virtual /* [local] */ HRESULT STDMETHODCALLTYPE Invoke(
/* [in] */ DISPID dispIdMember,
/* [in] */ REFIID riid,
/* [in] */ LCID lcid,
/* [in] */ WORD wFlags,
/* [out][in] */ DISPPARAMS *pDispParams,
/* [out] */ VARIANT *pVarResult,
/* [out] */ EXCEPINFO *pExcepInfo,
/* [out] */ UINT *puArgErr)
{
return GetIDOrInvoke(FALSE, wFlags, NULL, pDispParams, pVarResult, &dispIdMember);
}
};

ACDispatch.cpp

#include "StdAfx.h"
#include "./acdispatch.h"

/* Note: we initialized the ref count to zero to make the object
auto-deleted by script engine when bZeroRefCount is TRUE,
*NEVER* call Release() in constructor */
CACAutoDispatch::CACAutoDispatch(BOOL bZeroRefCount) : m_uRefCount(1)
{
if (bZeroRefCount) m_uRefCount = 0;
}

CACAutoDispatch::~CACAutoDispatch(void)
{
}

HRESULT STDMETHODCALLTYPE CACAutoDispatch::QueryInterface(
/* [in] */ REFIID riid,
/* [iid_is][out] */ void **ppvObject)
{
if ( riid == IID_IUnknown || riid == IID_IDispatch )
{
this->AddRef();
*ppvObject = this;
return S_OK;
}
else
{
*ppvObject = NULL;
return E_NOINTERFACE;
}
}

ULONG STDMETHODCALLTYPE CACAutoDispatch::AddRef(void)
{
return ++m_uRefCount;
}

ULONG STDMETHODCALLTYPE CACAutoDispatch::Release(void)
{
ULONG ret = --m_uRefCount;
if (ret == 0) delete this;
return ret;
}

STDMETHODIMP CACAutoDispatch::GetTypeInfoCount(
/* [out] */ UINT *pctinfo)
{
return E_NOTIMPL;
}

STDMETHODIMP CACAutoDispatch::GetTypeInfo(
/* [in] */ UINT iTInfo,
/* [in] */ LCID lcid,
/* [out] */ ITypeInfo **ppTInfo)
{
return E_NOTIMPL;
}

下面是用一个console工程测试的代码,测试的脚本环境当然是msscriptcontrol,真是方便亚。

// testcons2.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "conio.h"
#include "atlstr.h"
#include "d:/design/ac/acdispatch.h"
#include "comutil.h"

#import "c:/windows/system32/msscript.ocx"

class CBeeper2 : public CACAutoDispatch
{
private:
void beep(_variant_t msg, _variant_t& retval)
{
CString str = msg;
printf("beep:%s/n", str);
}
public:
CBeeper2(BOOL bZeroRefCount) : CACAutoDispatch(bZeroRefCount)
{
}
~CBeeper2()
{
}
public:
BEGIN_AC_DISPMAP(CBeeper2)
AC_DISP_FUNCTION(1, L"beep", beep)
END_AC_DISPMAP()
};

class CMyGlobal : public CACAutoDispatch
{
private:
void alert(_variant_t msg, _variant_t& retval)
{
CString str = msg;
printf("%s/n", str);
}
void add2(_variant_t v1, _variant_t v2, _variant_t& retval)
{
int p1 = v1;
int p2 = v2;
retval = p1 + p2;
}
int m_count;
void put_count(_variant_t v1)
{
m_count = v1;
}

void get_count(_variant_t& retval)
{
retval = m_count;
}

void get_beeper(_variant_t& retval)
{
// init ref count to 1
retval = new CBeeper2(FALSE);
}
public:
CMyGlobal(BOOL bZeroRefCount) : CACAutoDispatch(bZeroRefCount)
{
m_count = 0;
}
~CMyGlobal()
{
}
public:
BEGIN_AC_DISPMAP(CMyGlobal)
AC_DISP_FUNCTION(1, L"alert", alert)
AC_DISP_FUNCTION(2, L"add", add2)
AC_DISP_PROP(3, L"count", get_count, put_count)
AC_DISP_READONLYPROP(4, L"beeper", get_beeper)
END_AC_DISPMAP()
};

using namespace MSScriptControl;

int _tmain(int argc, _TCHAR* argv[])
{
::CoInitialize(NULL);
{
IScriptControlPtr pCtrl;
pCtrl.CreateInstance(__uuidof(ScriptControl));
pCtrl->put_Language(_bstr_t("javascript"));
pCtrl->AddObject( _bstr_t("myglobal"), new CMyGlobal(TRUE), VARIANT_TRUE );
/* 以下这句将打印出beep:3 */
pCtrl->ExecuteStatement("count = 2; beeper.beep(add('1', count));");
pCtrl = NULL;
}
::CoUninitialize();
getch();
return 0;
}

 

本文地址:http://www.45fan.com/dnjc/70962.html
Tags: 实现 脚本 IDispatch
编辑:路饭网
关于我们 | 联系我们 | 友情链接 | 网站地图 | Sitemap | App | 返回顶部