如何取得variant内含的数组的首元素的地址
r...........t
[解决办法]
'---------------------------------------------------
' 过程名 : TestVariant
' 时间 : 2013/3/30
' 作者 : 杨过.网狐.cn(csdn bcrun)
' 功能 :
' 说明 :
' 备注 : 星辰设计室VB一群:283362041,星辰学园BASIC辅导群:289219875
'---------------------------------------------------
Public Sub TestVariant()
Dim arrVar As Variant
Debug.Print TypeName(arrVar)
arrVar = Array("a1", "b2", "c3")
Debug.Print TypeName(arrVar)
Debug.Print TypeName(arrVar(LBound(arrVar)))
Debug.Print VarPtr(arrVar(LBound(arrVar))) '数组的首元素的地址
End Sub
typedef struct FARSTRUCT tagVARIANT VARIANT;
typedef struct FARSTRUCT tagVARIANT VARIANTARG;
typedef struct tagVARIANT {
VARTYPE vt;
unsigned short wReserved1;
unsigned short wReserved2;
unsigned short wReserved3;
union {
unsigned char bVal; // VT_UI1.
short iVal; // VT_I2 .
long lVal; // VT_I4 .
float fltVal; // VT_R4 .
double dblVal; // VT_R8 .
VARIANT_BOOL boolVal; // VT_BOOL.
SCODE scode; // VT_ERROR.
CY cyVal; // VT_CY .
DATE date; // VT_DATE.
BSTR bstrVal; // VT_BSTR.
IUnknown FAR* punkVal; // VT_UNKNOWN.
IDispatch FAR* pdispVal; // VT_DISPATCH.
SAFEARRAY FAR* parray; // VT_ARRAY
[解决办法]
*.
unsigned char FAR* pbVal; // VT_BYREF
[解决办法]
VT_UI1.
short FAR* piVal; // VT_BYREF
[解决办法]
VT_I2.
long FAR* plVal; // VT_BYREF
[解决办法]
VT_I4.
float FAR* pfltVal; // VT_BYREF
[解决办法]
VT_R4.
double FAR* pdblVal; // VT_BYREF
------解决方案--------------------
VT_R8.
VARIANT_BOOL FAR* pboolVal; // VT_BYREF
[解决办法]
VT_BOOL.
SCODE FAR* pscode; // VT_BYREF
[解决办法]
VT_ERROR.
CY FAR* pcyVal; // VT_BYREF
[解决办法]
VT_CY.
DATE FAR* pdate; // VT_BYREF
[解决办法]
VT_DATE.
BSTR FAR* pbstrVal; // VT_BYREF
[解决办法]
VT_BSTR.
IUnknown FAR* FAR* ppunkVal; // VT_BYREF
[解决办法]
VT_UNKNOWN.
IDispatch FAR* FAR* ppdispVal; // VT_BYREF
[解决办法]
VT_DISPATCH.
SAFEARRAY FAR* FAR* pparray; // VT_ARRAY
[解决办法]
*.
VARIANT FAR* pvarVal; // VT_BYREF
[解决办法]
VT_VARIANT.
void FAR* byref; // Generic ByRef.
};
};
Option Explicit
Type userVARIANT
vt As Integer
wReserved1 As Integer
wReserved2 As Integer
wReserved3 As Integer
dwReserved1 As Long
dwReserved2 As Long
End Type
Const VT_BYREF = &H4000
Sub Main()
Dim arrVar As Variant
Dim a() As Byte
ReDim a(2)
Debug.Print Hex(VarPtr(a(0)))
arrVar = a
Debug.Print Hex(GetpvData(VarPtr(arrVar)))
TestByRef a
TestByVal a
End Sub
Function GetpvData(ByVal pV As Long) As Long
Dim v As userVARIANT
Dim sa As SafeArray
Dim pSA As Long
CopyMemory v, ByVal pV, Len(v)
If CBool(v.vt And VT_BYREF) Then
CopyMemory pSA, ByVal v.dwReserved1, 4
Else
pSA = v.dwReserved1
End If
CopyMemory sa, ByVal pSA, Len(sa)
GetpvData = sa.pvData
End Function
Sub TestByRef(ByRef arrVar As Variant)
Debug.Print Hex(GetpvData(VarPtr(arrVar)))
End Sub
Sub TestByVal(ByVal arrVar As Variant)
Debug.Print Hex(GetpvData(VarPtr(arrVar)))
End Sub
获取安全数组信息
Des:
获取安全数组的信息,包括安全数组结构内的所有数据
本来用结构做的话,更方便,但会增加代码量,而且用起来也会麻烦些,所以就用了N多变量了
有兴趣的朋友可以再改改
Private Function GetSafeArrayInfo(AnyArray As Variant, Optional sDimension As Integer, Optional LowerBound As Long, Optional UpperBound As Long, Optional Elements As Long, Optional Flags As Integer, Optional cbElements As Long, Optional cLocks As Long, Optional AddressOfData As Long) As Long
'**************************************************************
'*
'* 数组头地址 = GetSafeArrayInfo(数组 ,[维数],[下标],[上标],[元素个数],[属性],[元素长度],[锁定计数],[首元素地址])
'*
'* result: 成功返回数组头地址; 返回 0 代表这是一个未被初始化过的数组
'*
'* note: 除第1个参数外,均为输出型参数,要获取数组的什么信息,传入相应的变量,执行后,变量的值即为相应的数组数据
'*
'* 要获取多维数组的非第1维的上/下标,应按照下面的方法调用
'*
'* GetSafeArrayInfo (数组, 指定一个维数,[下标],[上标]
'*
'**************************************************************
Dim ArrayHeaderAddress As Long
Dim DimensionCount As Integer '维数计次
CopyMemory ArrayHeaderAddress, ByVal VarPtr(AnyArray) + 8, 4
CopyMemory ArrayHeaderAddress, ByVal ArrayHeaderAddress, 4 '获取数组头地址
If ArrayHeaderAddress < 1 Then Exit Function
CopyMemory DimensionCount, ByVal ArrayHeaderAddress, 2 '获取数组维数
If sDimension > DimensionCount Then Exit Function '若指定的维数大于实际维数则退出
CopyMemory LowerBound, ByVal (ArrayHeaderAddress + 16 + (DimensionCount - sDimension) * 8) + 4, 4 '获取下标
CopyMemory Elements , ByVal (ArrayHeaderAddress + 16 + (DimensionCount - sDimension) * 8), 4
'获取指定维数下的元素个数
UpperBound = Elements + LowerBound - 1 '获取指定维数下的上标
CopyMemory Flags, ByVal ArrayHeaderAddress + 2, 2 '获取数组属性
CopyMemory cbElements, ByVal ArrayHeaderAddress + 4, 2 '获取数组单个元素长度
CopyMemory cLocks, ByVal ArrayHeaderAddress + 8, 2 '获取数组锁定计数
CopyMemory AddressOfData, ByVal ArrayHeaderAddress + 12, 4 '获取数组首元素地址
GetSafeArrayInfo = ArrayHeaderAddress
End Function