本帖最后由 MyLiberal 于 2012-12-03 21:02:21 编辑

解决方案 »

  1.   

    IDispatch*还有一个作用是它不需要遵循COM接口中的不变性原则,后来的接口可以不用实现先前版本的部分功能.你这个IDispatch*是call back模式中的sink部分,在idl签名中作为dispinteface出现,以IxxxEvent的名称一般ocx文档中会规定它需要何种event recipient接口,你将实现了这种功能的接口,作为IDispatch*传给ocx的source(connection point)接口,当ocx线程检测到有event发生时,它会callback你的IDispatch.用OLE viewer打开你的ocx,一看便知这个接口需要实现什么方法...
      

  2.   

    用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里说的也不清楚。
      

  3.   

    OLE viewer里面看看dispinterface类型的接口,是否有IxxxEvent接口定义...
      

  4.   

    OnCall(...)就是这个的Event接口,如果找得到接口定义最好,如果找不到,可以用ATL或什么,自定义一个dual接口,其中Vtable的方法包含OnCall()的,具体参数还要自己琢磨,然后将这个对象的IDispatch*传给CallEvent。
      

  5.   

    OLE viewer里面看到的
    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);
      

  6.   

    _IEdCallEvents就是Event sink必须实现的接口,但是方法和OnCall()有些不一样,估计原作者留了一手,或者还有一个什么签名文件。你只有根据OnCall()的参数类型,自己实现dual接口了,反正调用IDispatch只看名字字符串,不会比对IID的。
      

  7.   

    太感谢了,找了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组件的事件一般都用的是这种形式的接口。 
      

  8.   

    这个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 是个什么类型,后来就开始搜这些资料,发现越挖越深,越挖越糊涂