COM动态添加删除成员,类似JavaScript中调用的对象

在JavaScript中调用对象时,可动态添加删除成员如:

var obj=new Object;
obj.member1='aaaaa';
obj.fun1=function()
{
    alert('fun1');
}


 

查了好些资料,原来Object这个COM对象,是实现了IDispatchEx接口
JS在调用对象成员之前,先利用IDispatchEx::GetDispID(成员名) 判断成员是否存在
那么在VC++中编写COM对象时即可以这样 在GetDispID中 添加对应的成员即可
//类头文件
class CSRObject	:public IDispatchEx
{
	CSRObject(void);
	~CSRObject(void);
	virtual HRESULT STDMETHODCALLTYPE GetDispID( __RPC__in BSTR bstrName, DWORD grfdex, __RPC__out DISPID *pid );
	
	virtual HRESULT STDMETHODCALLTYPE InvokeEx( DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller );
	
	virtual HRESULT STDMETHODCALLTYPE DeleteMemberByName( __RPC__in BSTR bstrName, DWORD grfdex );
	virtual HRESULT STDMETHODCALLTYPE QueryInterface( REFIID riid, void **ppvObject );
         //省略若干虚函数实现...
}

HRESULT STDMETHODCALLTYPE CSRObject::QueryInterface( REFIID riid, void **ppvObject )
{
	if (riid==IID_IUnknown)
	{
		*ppvObject = (CSRObject *)this;
	}else if (riid==IID_IDispatch)
	{
		*ppvObject = (CSRObject *)this;
	}else if (riid==IID_IDispatchEx)
	{
		*ppvObject = (CSRObject *)this;
                  //IDispatchEx接口
	}else{
		*ppvObject = NULL;
		return(E_NOINTERFACE);
	}
	return S_OK;
}

//这里是JS按照成员名字查成员DISPID
//JS在调用成员前会先调用该函数
HRESULT STDMETHODCALLTYPE CSRObject::GetDispID( __RPC__in BSTR bstrName, DWORD grfdex, __RPC__out DISPID *pid )
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
		
         if(grfdex & fdexNameCaseInsensitive) 
		//如果有fdexNameCaseInsensitive标志,查找成员名时忽略大小写
	
	if (成员不存在 && grfdex & fdexNameEnsure)  	
		//如果成员不存在且有fdexNameEnsure标志,你需要动态的创建这个成员名
        	
	//存在成员返回S_OK,并且 *pid=该成员ID
                
        //没有该成员返回 DISP_E_UNKNOWNNAME
}

//这里才是真正的调用函数
HRESULT STDMETHODCALLTYPE CSRObject::InvokeEx( DISPID id, LCID lcid, WORD wFlags, DISPPARAMS *pdp, VARIANT *pvarRes, EXCEPINFO *pei, IServiceProvider *pspCaller )
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState());
        
        //参数:id 就是JS通过GetDispID得到的DISPID,你需要按照该ID判断此次调用的是什么函数

	if (wFlags & DISPATCH_PROPERTYGET && wFlags & DISPATCH_METHOD)
	{
                //比如在JS中的代码:
                //var n=xxx.getvalue([param]);
                //那么将会到这里来
	}else if (wFlags & DISPATCH_PROPERTYGET)	//获取属性值
	{	
                //比如在JS中的代码:
                //var n=xxx.value;
                //那么将会到这里来
	}else if (wFlags & DISPATCH_PROPERTYPUT) //设置属性值
	{
                //比如在JS中的代码:
                //xxx.value=n;
                //那么将会到这里来
	}else if (wFlags & DISPATCH_METHOD) //调用成员
	{
                //比如在JS中的代码:
                //xxx.getvalue();
                //那么将会到这里来
	}else{
		//其它情况暂时没遇到过
		return DISP_E_MEMBERNOTFOUND;
	}

	return hr;
}

备份: http://www.silenceret.com/view.asp?id=12
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值