先用void _variant_t::Attach( VARIANT& varSrc ) 然后用下面的来转换 COleDateTime vartodate(const _variant_t& var) { COleDateTime value; switch (var.vt) { case VT_DATE: { value = var.date; } break; case VT_EMPTY: case VT_NULL: value.SetStatus(COleDateTime::null); break; default: value.SetStatus(COleDateTime::null); TRACE(_T("Warning: 未处理的 _variant_t 类型值; 文件: %s; 行: %d\n"), __FILE__, __LINE__); } return value; }COleCurrency vartocy(const _variant_t& var) { COleCurrency value; switch (var.vt) { case VT_CY: value = (CURRENCY)var.cyVal; break; case VT_EMPTY: case VT_NULL: value.m_status = COleCurrency::null; break; default: value.m_status = COleCurrency::null; TRACE(_T("Warning: 未处理的 _variant_t 类型值; 文件: %s; 行: %d\n"), __FILE__, __LINE__); } return value; }bool vartobool(const _variant_t& var) { bool value = false; switch (var.vt) { case VT_BOOL: value = var.boolVal ? true : false; case VT_EMPTY: case VT_NULL: break; default: TRACE(_T("Warning: 未处理的 _variant_t 类型值; 文件: %s; 行: %d\n"), __FILE__, __LINE__); } return value; }BYTE vartoby(const _variant_t& var) { BYTE value = 0; switch (var.vt) { case VT_I1: case VT_UI1: value = var.bVal; break; case VT_NULL: case VT_EMPTY: value = 0; break; default: TRACE(_T("Warning: 未处理的 _variant_t 类型值; 文件: %s; 行: %d\n"), __FILE__, __LINE__); } return value; }short vartoi(const _variant_t& var) { short value = 0; switch (var.vt) { case VT_BOOL: value = var.boolVal; break; case VT_UI1: case VT_I1: value = var.bVal; break; case VT_I2: case VT_UI2: value = var.iVal; break; case VT_NULL: case VT_EMPTY: value = 0; break; default: TRACE(_T("Warning: 未处理的 _variant_t 类型值; 文件: %s; 行: %d\n"), __FILE__, __LINE__); } return value; }long vartol(const _variant_t& var) { long value = 0; switch (var.vt) { case VT_BOOL: value = var.boolVal; break; case VT_UI1: case VT_I1: value = var.bVal; break; case VT_UI2: case VT_I2: value = var.iVal; break; case VT_I4: case VT_UI4: value = var.lVal; break; case VT_INT: value = var.intVal; break; case VT_R4: value = (long)(var.fltVal + 0.5); break; case VT_R8: value = (long)(var.dblVal + 0.5); break; case VT_DECIMAL: value = (long)var; break; case VT_CY: value = (long)var; break; case VT_BSTR://字符串 case VT_LPSTR://字符串 case VT_LPWSTR://字符串 value = atol((LPCTSTR)(_bstr_t)var); break; case VT_NULL: case VT_EMPTY: value = 0; break; default: TRACE(_T("Warning: 未处理的 _variant_t 类型值; 文件: %s; 行: %d\n"), __FILE__, __LINE__); } return value; }double vartof(const _variant_t& var) { double value = 0; switch (var.vt) { case VT_R4: value = var.fltVal; break; case VT_R8: value = var.dblVal; break; case VT_DECIMAL: value = (double)var; break; case VT_CY: value = (double)var; break; case VT_BOOL: value = var.boolVal; break; case VT_UI1: case VT_I1: value = var.bVal; break; case VT_UI2: case VT_I2: value = var.iVal; break; case VT_UI4: case VT_I4: value = var.lVal; break; case VT_INT: value = var.intVal; break; case VT_BSTR://字符串 case VT_LPSTR://字符串 case VT_LPWSTR://字符串 value = atof((LPCTSTR)(_bstr_t)var); break; case VT_NULL: case VT_EMPTY: value = 0; break; default: value = 0; TRACE(_T("Warning: 未处理的 _variant_t 类型值; 文件: %s; 行: %d\n"), __FILE__, __LINE__); } return value; }CString vartostr(const _variant_t &var) { CString strValue;
switch (var.vt) { case VT_BSTR://字符串 case VT_LPSTR://字符串 case VT_LPWSTR://字符串 strValue = (LPCTSTR)(_bstr_t)var; break; case VT_I1: case VT_UI1: strValue.Format("%d", var.bVal); break; case VT_I2://短整型 strValue.Format("%d", var.iVal); break; case VT_UI2://无符号短整型 strValue.Format("%d", var.uiVal); break; case VT_INT://整型 strValue.Format("%d", var.intVal); break; case VT_I4: //整型 strValue.Format("%d", var.lVal); break; case VT_I8: //长整型 strValue.Format("%d", var.lVal); break; case VT_UINT://无符号整型 strValue.Format("%d", var.uintVal); break; case VT_UI4: //无符号整型 strValue.Format("%d", var.ulVal); break; case VT_UI8: //无符号长整型 strValue.Format("%d", var.ulVal); break; case VT_VOID: strValue.Format("%8x", var.byref); break; case VT_R4://浮点型 strValue.Format("%.4f", var.fltVal); break; case VT_R8://双精度型 strValue.Format("%.8f", var.dblVal); break; case VT_DECIMAL: //小数 strValue.Format("%.8f", (double)var); break; case VT_CY: { COleCurrency cy = var.cyVal; strValue = cy.Format(); } break; case VT_BLOB: case VT_BLOB_OBJECT: case 0x2011: strValue = "[BLOB]"; break; case VT_BOOL://布尔型 strValue = var.boolVal ? "TRUE" : "FALSE"; break; case VT_DATE: //日期型 { DATE dt = var.date; COleDateTime da = COleDateTime(dt); strValue = da.Format("%Y-%m-%d %H:%M:%S"); } break; case VT_NULL://NULL值 strValue = ""; break; case VT_EMPTY://空 strValue = ""; break; case VT_UNKNOWN://未知类型 default: strValue = "UN_KNOW"; break; } return strValue; }
VARIANT 是一个结构,定义如下: struct tagVARIANT { union { struct __tagVARIANT { VARTYPE vt; WORD wReserved1; WORD wReserved2; WORD wReserved3; union { LONGLONG llVal; LONG lVal; BYTE bVal; SHORT iVal; FLOAT fltVal; DOUBLE dblVal; VARIANT_BOOL boolVal; _VARIANT_BOOL bool; SCODE scode; CY cyVal; DATE date; BSTR bstrVal; IUnknown *punkVal; IDispatch *pdispVal; SAFEARRAY *parray; BYTE *pbVal; SHORT *piVal; LONG *plVal; LONGLONG *pllVal; FLOAT *pfltVal; DOUBLE *pdblVal; VARIANT_BOOL *pboolVal; _VARIANT_BOOL *pbool; SCODE *pscode; CY *pcyVal; DATE *pdate; BSTR *pbstrVal; IUnknown **ppunkVal; IDispatch **ppdispVal; SAFEARRAY **pparray; VARIANT *pvarVal; PVOID byref; CHAR cVal; USHORT uiVal; ULONG ulVal; ULONGLONG ullVal; INT intVal; UINT uintVal; DECIMAL *pdecVal; CHAR *pcVal; USHORT *puiVal; ULONG *pulVal; ULONGLONG *pullVal; INT *pintVal; UINT *puintVal; struct __tagBRECORD { PVOID pvRecord; IRecordInfo *pRecInfo; } __VARIANT_NAME_4; } __VARIANT_NAME_3; } __VARIANT_NAME_2; DECIMAL decVal; } __VARIANT_NAME_1; } ; // 摘自VC.NET OAIDL.H 其中 vt 标识了该变量当前的类型,其值为VT_BSTR 等,在VB中就是用这个实现未定义类型的变量的,只有其值为VT_BSTR时这个变量才能获得其字符串 vt的取值如下 /* * VARENUM usage key, * * * [V] - may appear in a VARIANT * * [T] - may appear in a TYPEDESC * * [P] - may appear in an OLE property set * * [S] - may appear in a Safe Array * * * VT_EMPTY [V] [P] nothing * VT_NULL [V] [P] SQL style Null * VT_I2 [V][T][P][S] 2 byte signed int * VT_I4 [V][T][P][S] 4 byte signed int * VT_R4 [V][T][P][S] 4 byte real * VT_R8 [V][T][P][S] 8 byte real * VT_CY [V][T][P][S] currency * VT_DATE [V][T][P][S] date * VT_BSTR [V][T][P][S] OLE Automation string * VT_DISPATCH [V][T] [S] IDispatch * * VT_ERROR [V][T][P][S] SCODE * VT_BOOL [V][T][P][S] True=-1, False=0 * VT_VARIANT [V][T][P][S] VARIANT * * VT_UNKNOWN [V][T] [S] IUnknown * * VT_DECIMAL [V][T] [S] 16 byte fixed point * VT_RECORD [V] [P][S] user defined type * VT_I1 [V][T][P][s] signed char * VT_UI1 [V][T][P][S] unsigned char * VT_UI2 [V][T][P][S] unsigned short * VT_UI4 [V][T][P][S] unsigned long * VT_I8 [T][P] signed 64-bit int * VT_UI8 [T][P] unsigned 64-bit int * VT_INT [V][T][P][S] signed machine int * VT_UINT [V][T] [S] unsigned machine int * VT_INT_PTR [T] signed machine register size width * VT_UINT_PTR [T] unsigned machine register size width * VT_VOID [T] C style void * VT_HRESULT [T] Standard return type * VT_PTR [T] pointer type * VT_SAFEARRAY [T] (use VT_ARRAY in VARIANT) * VT_CARRAY [T] C style array * VT_USERDEFINED [T] user defined type * VT_LPSTR [T][P] null terminated string * VT_LPWSTR [T][P] wide null terminated string * VT_FILETIME [P] FILETIME * VT_BLOB [P] Length prefixed bytes * VT_STREAM [P] Name of the stream follows * VT_STORAGE [P] Name of the storage follows * VT_STREAMED_OBJECT [P] Stream contains an object * VT_STORED_OBJECT [P] Storage contains an object * VT_VERSIONED_STREAM [P] Stream with a GUID version * VT_BLOB_OBJECT [P] Blob contains an object * VT_CF [P] Clipboard format * VT_CLSID [P] A Class ID * VT_VECTOR [P] simple counted array * VT_ARRAY [V] SAFEARRAY* * VT_BYREF [V] void* for local use * VT_BSTR_BLOB Reserved for system use */ // 摘自wtypes.h 因为不同的值用union使其在同一内存空间中,所以使用前要先检查有效性,V_BSTR是一个宏,展开后是(&var)->bstrVal,而VARIANT的类型如果不是VT_BSTR可能会导致程序崩溃,所以上面代码应该改成 if(V_VT(&var) == VT_BSTR) CString str(V_BSTR(&var)); else // do sth.
...CString str(V_BSTR(&var));
VARIANT var;
...CString str(V_BSTR(&var));
然后用下面的来转换
COleDateTime vartodate(const _variant_t& var)
{
COleDateTime value;
switch (var.vt)
{
case VT_DATE:
{
value = var.date;
}
break;
case VT_EMPTY:
case VT_NULL:
value.SetStatus(COleDateTime::null);
break;
default:
value.SetStatus(COleDateTime::null);
TRACE(_T("Warning: 未处理的 _variant_t 类型值; 文件: %s; 行: %d\n"), __FILE__, __LINE__);
}
return value;
}COleCurrency vartocy(const _variant_t& var)
{
COleCurrency value;
switch (var.vt)
{
case VT_CY:
value = (CURRENCY)var.cyVal;
break;
case VT_EMPTY:
case VT_NULL:
value.m_status = COleCurrency::null;
break;
default:
value.m_status = COleCurrency::null;
TRACE(_T("Warning: 未处理的 _variant_t 类型值; 文件: %s; 行: %d\n"), __FILE__, __LINE__);
}
return value;
}bool vartobool(const _variant_t& var)
{
bool value = false;
switch (var.vt)
{
case VT_BOOL:
value = var.boolVal ? true : false;
case VT_EMPTY:
case VT_NULL:
break;
default:
TRACE(_T("Warning: 未处理的 _variant_t 类型值; 文件: %s; 行: %d\n"), __FILE__, __LINE__);
}
return value;
}BYTE vartoby(const _variant_t& var)
{
BYTE value = 0;
switch (var.vt)
{
case VT_I1:
case VT_UI1:
value = var.bVal;
break;
case VT_NULL:
case VT_EMPTY:
value = 0;
break;
default:
TRACE(_T("Warning: 未处理的 _variant_t 类型值; 文件: %s; 行: %d\n"), __FILE__, __LINE__);
}
return value;
}short vartoi(const _variant_t& var)
{
short value = 0;
switch (var.vt)
{
case VT_BOOL:
value = var.boolVal;
break;
case VT_UI1:
case VT_I1:
value = var.bVal;
break;
case VT_I2:
case VT_UI2:
value = var.iVal;
break;
case VT_NULL:
case VT_EMPTY:
value = 0;
break;
default:
TRACE(_T("Warning: 未处理的 _variant_t 类型值; 文件: %s; 行: %d\n"), __FILE__, __LINE__);
}
return value;
}long vartol(const _variant_t& var)
{
long value = 0;
switch (var.vt)
{
case VT_BOOL:
value = var.boolVal;
break;
case VT_UI1:
case VT_I1:
value = var.bVal;
break;
case VT_UI2:
case VT_I2:
value = var.iVal;
break;
case VT_I4:
case VT_UI4:
value = var.lVal;
break;
case VT_INT:
value = var.intVal;
break;
case VT_R4:
value = (long)(var.fltVal + 0.5);
break;
case VT_R8:
value = (long)(var.dblVal + 0.5);
break;
case VT_DECIMAL:
value = (long)var;
break;
case VT_CY:
value = (long)var;
break;
case VT_BSTR://字符串
case VT_LPSTR://字符串
case VT_LPWSTR://字符串
value = atol((LPCTSTR)(_bstr_t)var);
break;
case VT_NULL:
case VT_EMPTY:
value = 0;
break;
default:
TRACE(_T("Warning: 未处理的 _variant_t 类型值; 文件: %s; 行: %d\n"), __FILE__, __LINE__);
}
return value;
}double vartof(const _variant_t& var)
{
double value = 0;
switch (var.vt)
{
case VT_R4:
value = var.fltVal;
break;
case VT_R8:
value = var.dblVal;
break;
case VT_DECIMAL:
value = (double)var;
break;
case VT_CY:
value = (double)var;
break;
case VT_BOOL:
value = var.boolVal;
break;
case VT_UI1:
case VT_I1:
value = var.bVal;
break;
case VT_UI2:
case VT_I2:
value = var.iVal;
break;
case VT_UI4:
case VT_I4:
value = var.lVal;
break;
case VT_INT:
value = var.intVal;
break;
case VT_BSTR://字符串
case VT_LPSTR://字符串
case VT_LPWSTR://字符串
value = atof((LPCTSTR)(_bstr_t)var);
break;
case VT_NULL:
case VT_EMPTY:
value = 0;
break;
default:
value = 0;
TRACE(_T("Warning: 未处理的 _variant_t 类型值; 文件: %s; 行: %d\n"), __FILE__, __LINE__);
}
return value;
}CString vartostr(const _variant_t &var)
{
CString strValue;
switch (var.vt)
{
case VT_BSTR://字符串
case VT_LPSTR://字符串
case VT_LPWSTR://字符串
strValue = (LPCTSTR)(_bstr_t)var;
break;
case VT_I1:
case VT_UI1:
strValue.Format("%d", var.bVal);
break;
case VT_I2://短整型
strValue.Format("%d", var.iVal);
break;
case VT_UI2://无符号短整型
strValue.Format("%d", var.uiVal);
break;
case VT_INT://整型
strValue.Format("%d", var.intVal);
break;
case VT_I4: //整型
strValue.Format("%d", var.lVal);
break;
case VT_I8: //长整型
strValue.Format("%d", var.lVal);
break;
case VT_UINT://无符号整型
strValue.Format("%d", var.uintVal);
break;
case VT_UI4: //无符号整型
strValue.Format("%d", var.ulVal);
break;
case VT_UI8: //无符号长整型
strValue.Format("%d", var.ulVal);
break;
case VT_VOID:
strValue.Format("%8x", var.byref);
break;
case VT_R4://浮点型
strValue.Format("%.4f", var.fltVal);
break;
case VT_R8://双精度型
strValue.Format("%.8f", var.dblVal);
break;
case VT_DECIMAL: //小数
strValue.Format("%.8f", (double)var);
break;
case VT_CY:
{
COleCurrency cy = var.cyVal;
strValue = cy.Format();
}
break;
case VT_BLOB:
case VT_BLOB_OBJECT:
case 0x2011:
strValue = "[BLOB]";
break;
case VT_BOOL://布尔型 strValue = var.boolVal ? "TRUE" : "FALSE";
break;
case VT_DATE: //日期型
{
DATE dt = var.date;
COleDateTime da = COleDateTime(dt);
strValue = da.Format("%Y-%m-%d %H:%M:%S");
}
break;
case VT_NULL://NULL值
strValue = "";
break;
case VT_EMPTY://空
strValue = "";
break;
case VT_UNKNOWN://未知类型
default:
strValue = "UN_KNOW";
break;
}
return strValue;
}
struct tagVARIANT
{
union
{
struct __tagVARIANT
{
VARTYPE vt;
WORD wReserved1;
WORD wReserved2;
WORD wReserved3;
union
{
LONGLONG llVal;
LONG lVal;
BYTE bVal;
SHORT iVal;
FLOAT fltVal;
DOUBLE dblVal;
VARIANT_BOOL boolVal;
_VARIANT_BOOL bool;
SCODE scode;
CY cyVal;
DATE date;
BSTR bstrVal;
IUnknown *punkVal;
IDispatch *pdispVal;
SAFEARRAY *parray;
BYTE *pbVal;
SHORT *piVal;
LONG *plVal;
LONGLONG *pllVal;
FLOAT *pfltVal;
DOUBLE *pdblVal;
VARIANT_BOOL *pboolVal;
_VARIANT_BOOL *pbool;
SCODE *pscode;
CY *pcyVal;
DATE *pdate;
BSTR *pbstrVal;
IUnknown **ppunkVal;
IDispatch **ppdispVal;
SAFEARRAY **pparray;
VARIANT *pvarVal;
PVOID byref;
CHAR cVal;
USHORT uiVal;
ULONG ulVal;
ULONGLONG ullVal;
INT intVal;
UINT uintVal;
DECIMAL *pdecVal;
CHAR *pcVal;
USHORT *puiVal;
ULONG *pulVal;
ULONGLONG *pullVal;
INT *pintVal;
UINT *puintVal;
struct __tagBRECORD
{
PVOID pvRecord;
IRecordInfo *pRecInfo;
} __VARIANT_NAME_4;
} __VARIANT_NAME_3;
} __VARIANT_NAME_2;
DECIMAL decVal;
} __VARIANT_NAME_1;
} ;
// 摘自VC.NET OAIDL.H
其中 vt 标识了该变量当前的类型,其值为VT_BSTR 等,在VB中就是用这个实现未定义类型的变量的,只有其值为VT_BSTR时这个变量才能获得其字符串
vt的取值如下
/*
* VARENUM usage key,
*
* * [V] - may appear in a VARIANT
* * [T] - may appear in a TYPEDESC
* * [P] - may appear in an OLE property set
* * [S] - may appear in a Safe Array
*
*
* VT_EMPTY [V] [P] nothing
* VT_NULL [V] [P] SQL style Null
* VT_I2 [V][T][P][S] 2 byte signed int
* VT_I4 [V][T][P][S] 4 byte signed int
* VT_R4 [V][T][P][S] 4 byte real
* VT_R8 [V][T][P][S] 8 byte real
* VT_CY [V][T][P][S] currency
* VT_DATE [V][T][P][S] date
* VT_BSTR [V][T][P][S] OLE Automation string
* VT_DISPATCH [V][T] [S] IDispatch *
* VT_ERROR [V][T][P][S] SCODE
* VT_BOOL [V][T][P][S] True=-1, False=0
* VT_VARIANT [V][T][P][S] VARIANT *
* VT_UNKNOWN [V][T] [S] IUnknown *
* VT_DECIMAL [V][T] [S] 16 byte fixed point
* VT_RECORD [V] [P][S] user defined type
* VT_I1 [V][T][P][s] signed char
* VT_UI1 [V][T][P][S] unsigned char
* VT_UI2 [V][T][P][S] unsigned short
* VT_UI4 [V][T][P][S] unsigned long
* VT_I8 [T][P] signed 64-bit int
* VT_UI8 [T][P] unsigned 64-bit int
* VT_INT [V][T][P][S] signed machine int
* VT_UINT [V][T] [S] unsigned machine int
* VT_INT_PTR [T] signed machine register size width
* VT_UINT_PTR [T] unsigned machine register size width
* VT_VOID [T] C style void
* VT_HRESULT [T] Standard return type
* VT_PTR [T] pointer type
* VT_SAFEARRAY [T] (use VT_ARRAY in VARIANT)
* VT_CARRAY [T] C style array
* VT_USERDEFINED [T] user defined type
* VT_LPSTR [T][P] null terminated string
* VT_LPWSTR [T][P] wide null terminated string
* VT_FILETIME [P] FILETIME
* VT_BLOB [P] Length prefixed bytes
* VT_STREAM [P] Name of the stream follows
* VT_STORAGE [P] Name of the storage follows
* VT_STREAMED_OBJECT [P] Stream contains an object
* VT_STORED_OBJECT [P] Storage contains an object
* VT_VERSIONED_STREAM [P] Stream with a GUID version
* VT_BLOB_OBJECT [P] Blob contains an object
* VT_CF [P] Clipboard format
* VT_CLSID [P] A Class ID
* VT_VECTOR [P] simple counted array
* VT_ARRAY [V] SAFEARRAY*
* VT_BYREF [V] void* for local use
* VT_BSTR_BLOB Reserved for system use
*/
// 摘自wtypes.h
因为不同的值用union使其在同一内存空间中,所以使用前要先检查有效性,V_BSTR是一个宏,展开后是(&var)->bstrVal,而VARIANT的类型如果不是VT_BSTR可能会导致程序崩溃,所以上面代码应该改成
if(V_VT(&var) == VT_BSTR)
CString str(V_BSTR(&var));
else
// do sth.
CString str(V_BSTR(&var));
因为COM中绝大多数都是使用BSTR (Unicode宽字符串)