COleVariant 本质上是一个枚举,用同一种类型来表达不同的子类型。如同boost中的variant。
COleVariant类是对VARIANT结构的封装。
VARIANT 结构包含两部分。其一是 VARTYPE 型的成员变量vt;其二是个联合类型,这个联合包含了VC常用的几乎所有类型。因为联合用的是相同的存储空间,因此对联合的内容的解释依赖于 vt。
例如,
若 vt 的值是 VT_UI2, 说明该联合被解释为short int. 并使用成员变量名 iVal。
若 vt 的的值是 VT_BSTR,说明该联合被解释为 BSTR 类型。并使用成员变量名 bstrVal。
若 vt 的的值是 VT_BSTR|VT_BYREF,说明该联合被解释为BSTR 型指针。并使用成员变量名 pbstrVal。
它的构造函数具有极为强大的功能,当对象构造时首先调用VariantInit进行 初始化,然后根据参数中的标准类型调用相应的构造函数,并使用VariantCopy进行转换赋值操作,当VARIANT对象不在有效范围时,它的析构函 数就会被自动调用,由于析构函数调用了VariantClear,因而相应的内存就会被自动清除。除此之外,COleVariant的赋值操作符在与 VARIANT类型转换中为我们提供极大的方便。
若从数据库返回的是简单类型,如 short, long, 等,则直接引用既可。(主持人注:COleVariant类重载了“=”操作符,所以常用类型可以直接转换)若返回的是字符串类型,则有可能是 bstrVal 或pbstrVal。依赖于数据库服务程序。 BSTR 实际上就是个unicode 字符串,CString 的构造函数和赋值操作都能直接识别这一类型。
AndySun问:
VARIANT结构的vt成员可以为值VT_DECIMAL,当然,这个值在MSDN的帮助中似乎没有,但在VARIANT定义的源文件中确实有它的定义,它是在wtypes.h文件中定义的。但我不明白怎样将VT_DECIMAL的数据转换成常用的C数据类型,更想知道 VT_DECIMAL中究竟存放的是一个怎样的数据,应怎样将这个数据显示出来。谢谢!
李海答:你可以使用COleVariant的ChangeType函数(相当于API函数VariantChangeType)将VT_DECIMAL转换为其他常用类型。
例子
1 [cpp] view plaincopyprint? 2 01.COleVariant var(3.6f); 3 02.float v = var.fltVal; 4 03.CString str("testCOleVariant"); 5 04.COleVariant var2(str); 6 05.CString cpStr(var2.bstrVal);
例子
01.CString CMFCPropertyGridProperty::m_strFormatChar = _T("%c"); 02.CString CMFCPropertyGridProperty::m_strFormatShort = _T("%d"); 03.CString CMFCPropertyGridProperty::m_strFormatLong = _T("%ld"); 04.CString CMFCPropertyGridProperty::m_strFormatUShort = _T("%u"); 05.CString CMFCPropertyGridProperty::m_strFormatULong = _T("%u"); 06.CString CMFCPropertyGridProperty::m_strFormatFloat = _T("%f"); 07.CString CMFCPropertyGridProperty::m_strFormatDouble = _T("%lf"); 08. 09.CString CMFCPropertyGridProperty::FormatProperty() 10.{ 11. ASSERT_VALID(this); 12. ASSERT_VALID(m_pWndList); 13. 14. COleVariant& var = m_varValue; 15. 16. CString strVal; 17. 18. ............. 19. 20. switch (var.vt) 21. { 22. case VT_BSTR: 23. strVal = var.bstrVal; 24. break; 25. 26. case VT_I2: 27. strVal.Format(m_strFormatShort, (short)var.iVal); 28. break; 29. 30. case VT_I4: 31. case VT_INT: 32. strVal.Format(m_strFormatLong, (long)var.lVal); 33. break; 34. 35. case VT_UI1: 36. if ((BYTE)var.bVal != 0) 37. { 38. strVal.Format(m_strFormatChar, (TCHAR)(BYTE)var.bVal); 39. } 40. break; 41. 42. case VT_UI2: 43. strVal.Format( m_strFormatUShort, var.uiVal); 44. break; 45. 46. case VT_UINT: 47. case VT_UI4: 48. strVal.Format(m_strFormatULong, var.ulVal); 49. break; 50. 51. case VT_R4: 52. strVal.Format(m_strFormatFloat, (float)var.fltVal); 53. break; 54. 55. case VT_R8: 56. strVal.Format(m_strFormatDouble, (double)var.dblVal); 57. break; 58. 59. case VT_BOOL: 60. strVal = var.boolVal == VARIANT_TRUE ? m_pWndList->m_strTrue : m_pWndList->m_strFalse; 61. break; 62. 63. default: 64. // Unsupported type 65. strVal = _T("*** error ***"); 66. } 67. 68. return strVal; 69.}
COleVariant框架内容
01.class COleVariant : public tagVARIANT 02.{ 03. COleVariant(LPCTSTR lpszSrc); 04. COleVariant(LPCTSTR lpszSrc, VARTYPE vtSrc); // used to set to ANSI string 05. COleVariant(CString& strSrc); 06. 07. COleVariant(BYTE nSrc); 08. COleVariant(short nSrc, VARTYPE vtSrc = VT_I2); 09. COleVariant(long lSrc, VARTYPE vtSrc = VT_I4); 10. COleVariant(const COleCurrency& curSrc); 11. 12. COleVariant(float fltSrc); 13. COleVariant(double dblSrc); 14. COleVariant(const COleDateTime& timeSrc); 15..................................... 16. const COleVariant& operator=(float fltSrc); 17. const COleVariant& operator=(double dblSrc); 18. const COleVariant& operator=(const COleDateTime& dateSrc); 19. 20. const COleVariant& operator=(const CByteArray& arrSrc); 21. const COleVariant& operator=(const CLongBinary& lbSrc); 22.}; 23. 24. void Clear(); 25. void ChangeType(VARTYPE vartype, LPVARIANT pSrc = NULL); 26. void Attach(VARIANT& varSrc); 27. VARIANT Detach(); 28. void GetByteArrayFromVariantArray(CByteArray& bytes); 29.void SetString(LPCTSTR lpszSrc, VARTYPE vtSrc); // used to set ANSI string 30. operator LPVARIANT(); 31. operator LPCVARIANT() const 32./ 33.struct tagVARIANT 34. { union 35. { 36. struct __tagVARIANT 37. { 38. VARTYPE vt; 39. ....................... 40. union 41. { 42. LONGLONG llVal; 43. LONG lVal; 44. BYTE bVal; 45. SHORT iVal; 46. FLOAT fltVal; 47. DOUBLE dblVal; 48. ........... 49. DATE date; 50. BSTR bstrVal; 51. IUnknown *punkVal; 52. IDispatch *pdispVal; 53. .............. 54. } 55. 56.COleVariant::COleVariant(float fltSrc) 57. { vt = VT_R4; fltVal = fltSrc; } 58._AFXDISP_INLINE COleVariant::COleVariant(CString& strSrc) 59. { vt = VT_EMPTY; *this = strSrc; } 60. 61.const COleVariant& COleVariant::operator=(const CString& strSrc) 62.{ 63. // Free up previous VARIANT 64. Clear(); 65. 66. vt = VT_BSTR; 67. bstrVal = strSrc.AllocSysString(); 68. 69. return *this; 70. } 71. 72.typedef unsigned short VARTYPE; 73. 75. * VARENUM usage key, 76. * 77. * * [V] - may appear in a VARIANT 78. * * [T] - may appear in a TYPEDESC 79. * * [P] - may appear in an OLE property set 80. * * [S] - may appear in a Safe Array 81. * 82. * 83. * VT_EMPTY [V] [P] nothing 84. * VT_NULL [V] [P] SQL style Null 85. * VT_I2 [V][T][P][S] 2 byte signed int 86. * VT_I4 [V][T][P][S] 4 byte signed int 87. * VT_R4 [V][T][P][S] 4 byte real 88. * VT_R8 [V][T][P][S] 8 byte real 89. * VT_CY [V][T][P][S] currency 90. * VT_DATE [V][T][P][S] date 91. * VT_BSTR [V][T][P][S] OLE Automation string 92. * VT_DISPATCH [V][T] [S] IDispatch * 93. * VT_ERROR [V][T][P][S] SCODE 94. * VT_BOOL [V][T][P][S] True=-1, False=0 95. * VT_VARIANT [V][T][P][S] VARIANT * 96. * VT_UNKNOWN [V][T] [S] IUnknown * 97. * VT_DECIMAL [V][T] [S] 16 byte fixed point 98. ....................................... 99. 100.enum VARENUM 101. { VT_EMPTY = 0, 102. VT_NULL = 1, 103. VT_I2 = 2, 104. VT_I4 = 3, 105. VT_R4 = 4, 106. VT_R8 = 5, 107. VT_CY = 6, 108. VT_DATE = 7, 109. VT_BSTR = 8, 110. ......................................... 111. } ;
COleVariant功能:
COleVariant类是对VARIANT结构的封装。它的构造函数具有极为强大的功能:
1、当对象构造时首先调用VariantInit进行 初始化,然后根据参数中的标准类型调用相应的构造函数,并使用VariantCopy进行转换赋值操作;
2、当VARIANT对象不在有效范围时,它的析构函 数就会被自动调用,由于析构函数调用了VariantClear,因而相应的内存就会被自动清除。
COleVariant是数据库常用到的数据类型。它可以是字串,整型值,日期等。知道怎样将它转换为CString很有用处。
例如:设有CString A; COleVariant B; 来看看怎样将COleVariant转换为CString:
switch(B.vt){
case VT_BSTR: A=V_BSTRT(&B); break;//COleVariant是一个字串
case VT_I2: A.Format(_T("%hd"),V_I2(&B));break;//是短整型
case VT_I4: A.Format(_T("%d"),V_I4(&B));break;//是长整型
case VT_R4: A.Format(_T("%e"),(double)V_R4(&B));break;//是浮点数
case VT_R8: A.Format(_T("%e"),V_R8(&B));break;//是浮点数
case VT_CY: A=COleCurrency(B).Format();break;//是货币值
case VT_DATE: A=COleDateTime(B).Format("%Y-%m-%d");break;//是日期
case VT_BOOL: A=V_BOOL(&B)?"True":"False";break;//是布尔值}