IDispatch,调度接口用VC怎么调用? 本帖最后由 MyLiberal 于 2012-12-03 21:02:21 编辑 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 IDispatch*还有一个作用是它不需要遵循COM接口中的不变性原则,后来的接口可以不用实现先前版本的部分功能.你这个IDispatch*是call back模式中的sink部分,在idl签名中作为dispinteface出现,以IxxxEvent的名称一般ocx文档中会规定它需要何种event recipient接口,你将实现了这种功能的接口,作为IDispatch*传给ocx的source(connection point)接口,当ocx线程检测到有event发生时,它会callback你的IDispatch.用OLE viewer打开你的ocx,一看便知这个接口需要实现什么方法... 用OleView看这个OCX文件,有两个同名的方法[id(0x00000003), propget]IDispatch* CallEvent();和[id(0x00000003), propputref]void CallEvent([in] IDispatch* rhs);请教我该怎么调用这两个函数。这个OCX本来是html调用的,现在我想给改成MFC调用,并且已经找不到这个OCX的作者了。HTML调用的方法是:obj1.CallEvent = OnCall;OnCall是一个JS函数:function OnCall(isin,sev, number, sj,st) { alert(isin+sev+number+sj+st);}当这个OCX获取到一些底层的数据后,会自动调用这个js函数OnCall,我现在就是想在MFC中实现这个OnCall函数。找了好多资料,都没找到propget和propputre的用法,MSDN里说的也不清楚。 OLE viewer里面看看dispinterface类型的接口,是否有IxxxEvent接口定义... OnCall(...)就是这个的Event接口,如果找得到接口定义最好,如果找不到,可以用ATL或什么,自定义一个dual接口,其中Vtable的方法包含OnCall()的,具体参数还要自己琢磨,然后将这个对象的IDispatch*传给CallEvent。 OLE viewer里面看到的dispinterfaces选项下有2个子选项dispinteface _IEdCallEvents和dispinteface IEdCalldispinteface _IEdCallEvents选项的内容是:[ uuid(DBD44AEA-8A8C-4B67-AA29-A2C627C66B33), helpstring("_IEdCallEvents Interface")]dispinterface _IEdCallEvents { properties: methods: [id(0x00000002), helpstring("method OnConnected")] void OnConnected([in] char* PeerID);};里边只有一个methods: OnConnected,内容是[id(0x00000002), helpstring("method OnConnected")]void OnConnected([in] char* PeerID); _IEdCallEvents就是Event sink必须实现的接口,但是方法和OnCall()有些不一样,估计原作者留了一手,或者还有一个什么签名文件。你只有根据OnCall()的参数类型,自己实现dual接口了,反正调用IDispatch只看名字字符串,不会比对IID的。 太感谢了,找了3天资料,一点头绪也没有,完全不知道咋下手啊怎么实现dual接口,您手上有这种例子吗?这方面资料我找到的都是一些理论上的东西,不知道咋进行下一步。==================================================================所谓的自动化接口就是用IDispatch实现的接口。我们已经讲解过IDispatch的作用了,它的好处就是脚本语言象VBScript、 JavaScript也能用COM组件了,从而基本上做到了与语言无关它的缺点主要有两个,第一个就是速度慢效率低。这是显而易见的,通过虚函数表一下子就可以调用函数了,而通过Invoke则等于中间转了道手续,尤其是需要把函数参数转换成一种规范的格式才去调用函数,耽误了很多时间。所以一般若非是迫不得已我们都想用VTable的方式调用函数以获得高效率。第二个缺点就是只能使用规定好的所谓的自动化数据类型。如果不用IDispatch我们可以想用什么数据类型就用什么类型,VC会自动给我们生成相应的调度代码。而用自动化接口就不行了,因为Invoke的实现代码是VC事先写好的,而它不能事先预料到我们要用到的所有类型,它只能根据一些常用的数据类型来写它的处理代码,而且它也要考虑不同语言之间的数据类型转换问题。所以VC自动化接口生成的调度代码只适用于它所规定好的那些数据类型,当然这些数据类型已经足够丰富了,但不能满足自定义数据结构的要求。你也可以自己写调度代码来处理你的自定义数据结构,但这并不是一件容易的事。考虑到IDispatch的种种缺点(它还有一个缺点,就是使用麻烦,:-) )现在一般都推荐写双接口组件,称为dual接口,实际上就是从IDispatch继承的接口。我们知道任何接口都必须从 IUnknown继承,IDispatch接口也不例外。那从IDispatch继承的接口实际上就等于有两个基类,一个是IUnknown,一个是IDispatch,所以它可以以两种方式来调用组件,可以通过 IUnknown用虚函数表的方式调用接口方法,也可以通过IDispatch::Invoke自动化调度来调用。这就有了很大的灵活性,这个组件既可以用于C++的环境也可以用于脚本语言中,同时满足了各方面的需要。 相对比的,dispinterface是一种纯粹的自动化接口,可以简单的就把它看作是IDispatch接口 (虽然它实际上不是的),这种接口就只能通过自动化的方式来调用,COM组件的事件一般都用的是这种形式的接口。 这个OCX已经被我作为一个控件加到窗体上了,普通的调用函数,都已经实现了,就差这几个函数不知道怎么调用。LPDISPATCH get_CallEvent() { LPDISPATCH result; InvokeHelper(0x3, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&result, NULL); return result; } void putref_CallEvent(LPDISPATCH newValue) { static BYTE parms[] = VTS_DISPATCH ; InvokeHelper(0x3, DISPATCH_PROPERTYPUTREF, VT_EMPTY, NULL, parms, newValue); }一开始我以为是通过putref_CallEvent 和 get_CallEvent来调用,但是不知道LPDISPATCH 是个什么类型,后来就开始搜这些资料,发现越挖越深,越挖越糊涂 关于区域文字背景的问题 我们的控件必须有个ID么? 请问如何清空char型的字符数组? 绝对坐标,以毫米为单位,如何转换成以像素为单位 关于窗口拆分的问题 C++中有没有可以直接计算向量叉积的函数呢? 誰有读truetype字体的源码? 创建一个无模对话框的问题! 求 : bmp 转换到 jpeg 的程序 如何动态的使一个窗口总在最前和去掉总在最前?多谢 【离职】 交接最后一天 请问如何获得进程的标题名
IDispatch* CallEvent();和[id(0x00000003), propputref]
void CallEvent([in] IDispatch* rhs);请教我该怎么调用这两个函数。这个OCX本来是html调用的,现在我想给改成MFC调用,并且已经找不到这个OCX的作者了。HTML调用的方法是:obj1.CallEvent = OnCall;
OnCall是一个JS函数:function OnCall(isin,sev, number, sj,st) {
alert(isin+sev+number+sj+st);
}
当这个OCX获取到一些底层的数据后,会自动调用这个js函数OnCall,我现在就是想在MFC中实现这个OnCall函数。找了好多资料,都没找到propget和propputre的用法,MSDN里说的也不清楚。
dispinterfaces选项下有2个子选项dispinteface _IEdCallEvents和dispinteface IEdCall
dispinteface _IEdCallEvents选项的内容是:[
uuid(DBD44AEA-8A8C-4B67-AA29-A2C627C66B33),
helpstring("_IEdCallEvents Interface")
]
dispinterface _IEdCallEvents {
properties:
methods:
[id(0x00000002), helpstring("method OnConnected")]
void OnConnected([in] char* PeerID);
};里边只有一个methods: OnConnected,内容是
[id(0x00000002), helpstring("method OnConnected")]
void OnConnected([in] char* PeerID);
怎么实现dual接口,您手上有这种例子吗?这方面资料我找到的都是一些理论上的东西,不知道咋进行下一步。
==================================================================
所谓的自动化接口就是用IDispatch实现的接口。我们已经讲解过IDispatch的作用了,它的好处就是脚本语言象VBScript、 JavaScript也能用COM组件了,从而基本上做到了与语言无关它的缺点主要有两个,第一个就是速度慢效率低。这是显而易见的,通过虚函数表一下子就可以调用函数了,而通过Invoke则等于中间转了道手续,尤其是需要把函数参数转换成一种规范的格式才去调用函数,耽误了很多时间。所以一般若非是迫不得已我们都想用VTable的方式调用函数以获得高效率。第二个缺点就是只能使用规定好的所谓的自动化数据类型。如果不用IDispatch我们可以想用什么数据类型就用什么类型,VC会自动给我们生成相应的调度代码。而用自动化接口就不行了,因为Invoke的实现代码是VC事先写好的,而它不能事先预料到我们要用到的所有类型,它只能根据一些常用的数据类型来写它的处理代码,而且它也要考虑不同语言之间的数据类型转换问题。所以VC自动化接口生成的调度代码只适用于它所规定好的那些数据类型,当然这些数据类型已经足够丰富了,但不能满足自定义数据结构的要求。你也可以自己写调度代码来处理你的自定义数据结构,但这并不是一件容易的事。考虑到IDispatch的种种缺点(它还有一个缺点,就是使用麻烦,:-) )现在一般都推荐写双接口组件,称为dual接口,实际上就是从IDispatch继承的接口。我们知道任何接口都必须从 IUnknown继承,IDispatch接口也不例外。那从IDispatch继承的接口实际上就等于有两个基类,一个是IUnknown,一个是IDispatch,所以它可以以两种方式来调用组件,可以通过 IUnknown用虚函数表的方式调用接口方法,也可以通过IDispatch::Invoke自动化调度来调用。这就有了很大的灵活性,这个组件既可以用于C++的环境也可以用于脚本语言中,同时满足了各方面的需要。 相对比的,dispinterface是一种纯粹的自动化接口,可以简单的就把它看作是IDispatch接口 (虽然它实际上不是的),这种接口就只能通过自动化的方式来调用,COM组件的事件一般都用的是这种形式的接口。
LPDISPATCH get_CallEvent() {
LPDISPATCH result;
InvokeHelper(0x3, DISPATCH_PROPERTYGET, VT_DISPATCH, (void*)&result, NULL);
return result;
}
void putref_CallEvent(LPDISPATCH newValue) {
static BYTE parms[] = VTS_DISPATCH ;
InvokeHelper(0x3, DISPATCH_PROPERTYPUTREF, VT_EMPTY, NULL, parms, newValue);
}
一开始我以为是通过putref_CallEvent 和 get_CallEvent来调用,但是不知道LPDISPATCH 是个什么类型,后来就开始搜这些资料,发现越挖越深,越挖越糊涂