1 简介

  • 自动化对象: 实现了IDispatch接口的COM对象
  • 属性: 自动化对象的数据特征
  • 方法: 指自动化对象所提供的功能服务, 可以包含参数

客户程序与自动化对象交互示意图
image.png

2 类型库 (typelib)

(1) 自动化兼容的数据类型VARIANT

  1. typedef struct tagVARIANT {
  2. union {
  3. struct __tagVARIANT {
  4. VARTYPE vt;
  5. WORD wReserved1;
  6. WORD wReserved2;
  7. WORD wReserved3;
  8. union {
  9. ULONGLONG ullVal; /* VT_UI8 */
  10. LONGLONG llVal; /* VT_I8 */
  11. LONG lVal; /* VT_I4 */
  12. BYTE bVal; /* VT_UI1 */
  13. SHORT iVal; /* VT_I2 */
  14. FLOAT fltVal; /* VT_R4 */
  15. DOUBLE dblVal; /* VT_R8 */
  16. VARIANT_BOOL boolVal; /* VT_BOOL */
  17. _VARIANT_BOOL bool; /* (obsolete) */
  18. SCODE scode; /* VT_ERROR */
  19. CY cyVal; /* VT_CY */
  20. DATE date; /* VT_DATE */
  21. BSTR bstrVal; /* VT_BSTR */
  22. IUnknown * punkVal; /* VT_UNKNOWN */
  23. IDispatch * pdispVal; /* VT_DISPATCH */
  24. SAFEARRAY * parray; /* VT_ARRAY */
  25. BYTE * pbVal; /* VT_BYREF|VT_UI1 */
  26. SHORT * piVal; /* VT_BYREF|VT_I2 */
  27. LONG * plVal; /* VT_BYREF|VT_I4 */
  28. LONGLONG * pllVal; /* VT_BYREF|VT_I8 */
  29. FLOAT * pfltVal; /* VT_BYREF|VT_R4 */
  30. DOUBLE * pdblVal; /* VT_BYREF|VT_R8 */
  31. VARIANT_BOOL *pboolVal; /* VT_BYREF|VT_BOOL */
  32. _VARIANT_BOOL *pbool; /* (obsolete) */
  33. SCODE * pscode; /* VT_BYREF|VT_ERROR */
  34. CY * pcyVal; /* VT_BYREF|VT_CY */
  35. DATE * pdate; /* VT_BYREF|VT_DATE */
  36. BSTR * pbstrVal; /* VT_BYREF|VT_BSTR */
  37. IUnknown ** ppunkVal; /* VT_BYREF|VT_UNKNOWN */
  38. IDispatch ** ppdispVal; /* VT_BYREF|VT_DISPATCH */
  39. SAFEARRAY ** pparray; /* VT_BYREF|VT_ARRAY */
  40. VARIANT * pvarVal; /* VT_BYREF|VT_VARIANT */
  41. PVOID byref; /* Generic ByRef */
  42. CHAR cVal; /* VT_I1 */
  43. USHORT uiVal; /* VT_UI2 */
  44. ULONG ulVal; /* VT_UI4 */
  45. INT intVal; /* VT_INT */
  46. UINT uintVal; /* VT_UINT */
  47. DECIMAL * pdecVal; /* VT_BYREF|VT_DECIMAL */
  48. CHAR * pcVal; /* VT_BYREF|VT_I1 */
  49. USHORT * puiVal; /* VT_BYREF|VT_UI2 */
  50. ULONG * pulVal; /* VT_BYREF|VT_UI4 */
  51. ULONGLONG * pullVal; /* VT_BYREF|VT_UI8 */
  52. INT * pintVal; /* VT_BYREF|VT_INT */
  53. UINT * puintVal; /* VT_BYREF|VT_UINT */
  54. struct __tagBRECORD {
  55. PVOID pvRecord;
  56. IRecordInfo * pRecInfo;
  57. } __VARIANT_NAME_4; /* VT_RECORD */
  58. } __VARIANT_NAME_3;
  59. } __VARIANT_NAME_2;
  60. DECIMAL decVal;
  61. } __VARIANT_NAME_1;
  62. }VARIANT;

(2) 字符串类型BSTR

image.png
OLE提供了一组API函数处理BSTR
SysAllocString、SysAllocStringLen、SysFreeString、SysReAllocString、SysReAllocStringLen以及SysStringLen等

(3) 数组类型SAFEARRAY

image.png

(4) 自动化数据类型的转换

  • Invoke函数的数据类型转换能力为弱数据类型开发环境提供了极大的便利
  • OLE提供了两个类型转换函数:
    • VariantChangeType
    • VariantChangeTypeEx
  • OLE也提供了一组专门的类型转换函数VarFrom, 比如:

    • VarR4FromI2
    • VarUI2FromDisp等

      3 参数传递

      1. IDispatch::Invoke(
      2. dispIdMember, // 指定DISPID
      3. lcid, // 指定本地化标识
      4. wFlags, // 指示调用类型 DISPATCH_METHOD、DISPATCH_PROPERTYGET、DISPATCH_PROPERTYPUT、 DISPATCH_PROPERTYPUTREF
      5. pDispParams, // 包括调用的参数数组、参数的DISPID数组、数组中参数个数等信息
      6. pVarResult, // 保存返回值信息
      7. puArgErr, // 错误参数的索引值
      8. )
      其中第四个参数的结构如下
      1. typedef struct tagDISPPARAMS
      2. {
      3. VARIANTARG *rgvarg; // 参数数组, 参数的顺序与客户程序中调用的参数左右顺序刚好相反
      4. DISPID *rgdispidNamedArgs; // 参数的分发ID数组
      5. UINT cArgs; // 数组中参数个数
      6. UINT cNamedArgs; // 命名参数个数
      7. } DISPPARAMS;

      (1) 参数顺序

      例如: Object.Method(arg0, arg1, arg2)
  • 对应Invoke函数的pDispParams参数的DISPPARAMS结构中,cArgs为3

  • rgarg数组的成员分别为:rgvarg[0]=arg2、rgvarg[1]=arg1、rgvarg[2]=arg0

    (2) 可选参数

  • IDL文件中,可以把方法的参数标记为可选的(optional)

  • 可选参数也会出现在DISPPARAMS结构中
  • 如果vt域为VT_ERROR并且scode域为DISP_E_PARAMNOTFOUND,则此参数为可选参数

    (3) 命名参数

    DISPPARAMS结构的cNamedArgs成员指定了在rgarg数组中命名参数的个数, 命名参数可以不受次序约束
    image.pngimage.png