paul ID:wingforward
11513次访问,排名9507(2)好友0人,关注者0
wingforward的文章
原创 25 篇
翻译 0 篇
转载 0 篇
评论 24 篇
最近评论
文章分类
    收藏
    相册
    存档
    软件项目交易
    订阅我的博客
    XML聚合  FeedSky
    订阅到鲜果
    订阅到Google
    订阅到抓虾
    订阅到BlogLines
    订阅到Yahoo
    订阅到GouGou
    订阅到飞鸽
    订阅到Rojo
    订阅到newsgator
    订阅到netvibes

    原创 自动化对象收藏

    新一篇: The Art of Computer Game Design--ACKNOWLEDGMENT & PREFACE  | 旧一篇: VC++开发BHO插件——定制你的浏览器  作者 陆其明

    所谓自动化对象,指的是实现了IDispatch接口的COM对象,IDispatch接口是自动化对象的一个重要标志。使用自动化技术的一个主要目的就是对COM的一些底层操作进行简化。包括自动化组件和自动化客户两方面的内容,分别用来定义和使用自动化对象。
     自动化对象包含有属性和方法这两种重要的组成。属性类似于类中的数据成员,方法则类似于类成员函数,只不过这里的属性只能被读取而不允许被写入。自动化组件除了定义自动化对象外,还将内部可编程对象展现给自动化客户,而自动化客户则对这些暴露的自动化对象进行操作。具体的操作包括:创建一个新的自动化对象,获取、设置自动化对象的属性,以及调用自动化对象的方法等。IDispatch接口作为自动化对象的重要特征,可以通过QuereyInterface()函数查询此接口来确定组件是否是自动化对象。IDispatch接口直接从IUnknown接口派生,接口定义如下:
    interface IDispatch : IUnknown
    {
     virtual HRESULT GetTypeInfoCount(UINT* pctinfo) = 0;
     virtual HRESULT GetTypeInfo(UINT itinfo, LCID lcid, ITypeInfo** pptinfo) = 0;
     virtual HRESULT GetIDsOfNames (REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid) = 0;
     virtual HRESULT Invoke(DISPID dispidMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr ) = 0;
    }

      其中,接口成员函数GetTypeInfoCount()用于获取自动化组件支持的ITypeInfo接口的数目。GetTypeInfo()用于获取指针ITypeInfo接口的指针,通过该指针将能够判断自动化服务程序所提供的自动化支持。剩下的这两个函数是比较重要的,其中GetIDsOfNames()将读取一个函数的名称并返回其调度ID(DISPID),DISPID只是一个long类型的数据,对于IDispatch的一个特定实现,此DISPID值应该是唯一的。其参数riid为保留参数,必须设置为IID_NULL,在rgszNames中指定了成员的函数名及其参数,由cNames标识了名字的个数,lcid参数用于指定本地化标识,得到的DISPID 将保存到rgdispid中。Invoke()提供了访问自动化对象暴露出来的方法和属性的方法。可以将DISPID作为函数指针数组的索引传入dispidMember参数,Invoke()将实现一组按此索引来访问的函数。riid和lcid的含义与在GetIDsOfNames()中的定义相同,分别为保留参数和本地化标识。WFlags参数指定了要访问的是接口的属性还是方法,pdispparams参数包括了方法和属性调用的参数数组、DISPID数组以及数组中参数个数等信息。pvarResult参数保存有返回值信息。pexcepinfo指向一个有效的异常信息结构,puArgErr参数包含了第一个产生错误的参数指针。通过GetIDsOfNames()和Invoke()的结合使用,将可以根据函数名称对方法和属性进行调用。这样,函数地址、AddRef()、Release()以及接口指针等细节问题将无需考虑。下面结合一段实例代码来说明对IDispatch接口的使用:

    // 从ProgID得到CLSID
    wchar_t progid[] = L"MSCAL.Calendar.7";
    CLSID clsid;
    if (FAILED(::CLSIDFromProgID(progid, &clsid)))
     return;
     // 得到IDispatch接口指针
    IDispatch* pIDispatch = NULL;
    if (FAILED(::CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IDispatch, (void**)&pIDispatch)))
     return;
    // 得到DISPID
    DISPID dispid;
    OLECHAR* func = L"Today";
    if (FAILED(pIDispatch->GetIDsOfNames(IID_NULL, &func, 1, GetUserDefaultLCID(), &dispid)))
     return;
    // 通过DISPID使用Today方法
    DISPPARAMS dispparams = {NULL};
    if (FAILED(pIDispatch->Invoke(dispid, IID_NULL, GetUserDefaultLCID(), DISPATCH_METHOD, &dispparams, NULL, NULL, NULL)))
     return;
    // 将日期移动到今天
    AfxMessageBox("日期成功移动到今天");

      这段代码使用的是Calendar组件,并通过IDispatch接口完成对Today()方法的调用。CLSIDFromProgID()将Calendar组件的ProgID转换为CLSID,并以此CLSID和IID_IDispatch作为参数去调用CoCreateInstance()以得到IDispatch接口指针。通过其成员函数GetIDsOfNames()得到将要调用的Today方法的DISPID,最后使用Invoke()成员函数执行此方法。

    发表于 @ 2005年01月12日 17:26:00|评论(loading...)|编辑

    新一篇: The Art of Computer Game Design--ACKNOWLEDGMENT & PREFACE  | 旧一篇: VC++开发BHO插件——定制你的浏览器  作者 陆其明

    评论:没有评论。

    发表评论  


    当前用户设置只有注册用户才能发表评论。如果你没有登录,请点击登录
    Csdn Blog version 3.1a
    Copyright © wingforward