作者在 2010-05-03 15:17:07 发布以下内容
'我们先理解一下数组的概念,数组是由一组连续的内存区域构成
'比如有一排连续的房间,每个房间都有一个编号,这个编号也是连续的。
'例如房间1、房间2、...房间n,这个n就是房间的编号,如果我对你说“请”到房间2
'拿一本书给我,那么你完成这个任务首先就是找到房间2,然后进入房间2拿到这本书。
'显而易见这个编号实际上就是地址
'那么,如果我们取得数组的首地址,那么我们就可以根据地址对数组进行各种操作。
'C语言提供了取得数组地址的语言特性,而VB则没有这样的语言特性,但我们依然可以
'通过API得到数组的地址。我们先来认识下这一个DLL--Msvbvm60.dll,这个是vb6.0
'的程序运行库,其就提供了一个可以获得数组地址的API,它的api声明如下:
Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" _
(ptr() As Any) As Long
'CopyMemory API请参照《VB指针教程1》,地址:http://bbs.bccn.net/thread-305122-1-1.html
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, Source As Any, ByVal Length As Long)
Private Sub Form_Load()
Dim arr(1 To 3) As Integer
For i = 1 To 3
arr(i) = i * 10
Next
Dim arraddr As Long
'取得arr数组的首地址
arraddr = VarPtrArray(arr)
Dim arr1 As Integer, arr2 As Integer, arr3 As Integer
CopyMemory arr1, ByVal arraddr, 2
CopyMemory arr2, ByVal arraddr + 2, 2
CopyMemory arr3, ByVal arraddr + 4, 2
List1.AddItem "arr(1)=" & arr1
List1.AddItem "arr(2)=" & arr2
List1.AddItem "arr(3)=" & arr3
End Sub
'观察运行的结果,显然不是我们所预期的,为什么呢?这是因为VB数组的存储结构不同于我们先前所说的。
'VB数组的存储结构是使用一种叫做SafeArray的结构,而VarPtrArray(arr)取得的即是指向SafeArray结
'构的指针,我们现在得先去了解下SafeArray结构:
'Private Type SafeArray
' cDims As Integer '指向数组维数的指针
' fFeatures As Integer '用来描述数组如何分配和如何被释放的标志
' cbElements As Long '指向数组元素所占的字节数的指针
' cLocks As Long '一个计数器,用来跟踪该数组被锁定的次数
' pvData As Long '指向数组内一个元素的指针,最重要的部分
' cElements As Long '数组元素的个数
' lLbound As Long '数组的下限
'End Type
''以下是fFeatures的常量标志
'Private Const FADF_AUTO As Integer = &H1 '在堆栈中执行的分配
'Private Const FADF_STATIC As Integer = &H2 '静态分配
'Private Const FADF_EMBEDDED As Integer = &H4 '在结构中创建
'Private Const FADF_FIXEDSIZE As Integer = &H10 '不能改变数组大小
'Private Const FADF_RECORD As Integer = &H20 '记录容器
'Private Const FADF_HAVEIID As Integer = &H40 '有IID 身份标记 数组
'Private Const FADF_HAVEVARTYPE As Integer = &H80 'VT 类型数组
'Private Const FADF_BSTR As Integer = &H100 'BSTR数组
'Private Const FADF_UNKNOWN As Integer = &H200 'IUnknown* 数组
'Private Const FADF_DISPATCH As Integer = &H400 'IDispatch* 数组
'Private Const FADF_VARIANT As Integer = &H800 'VARIANTs数组
'Private Const FADF_RESERVED As Integer = &HF008 '余留,将来使用
Private Sub Command1_Click()
List2.Clear
List3.Clear
Dim arr(1 To 3) As Integer
For i = 1 To 3
arr(i) = i * 10
Next
'指向SafeArrayld结构的指针
Dim SafeArrayldPoint As Long
'把arr数组的首地址复制到SafeArrayldPoint
CopyMemory SafeArrayldPoint, ByVal VarPtrArray(arr), 4
'数组的维数
Dim dims As Integer
CopyMemory dims, ByVal SafeArrayldPoint, 2
List2.AddItem "数组的维数:" & dims
Dim elements As Long
CopyMemory elements, ByVal SafeArrayldPoint + 4, 4
List2.AddItem "数组元素所占的字节数:" & elements
Dim eCount As Long
CopyMemory eCount, ByVal SafeArrayldPoint + 16, 4
List2.AddItem "数组元素的个数:" & eCount
Dim lBd As Long
CopyMemory lBd, ByVal SafeArrayldPoint + 20, 4
List2.AddItem "数组的下限:" & lBd
'读取数组的值
Dim arraddr As Long
CopyMemory arraddr, ByVal SafeArrayldPoint + 12, 4
Dim arr1 As Integer, arr2 As Integer, arr3 As Integer
CopyMemory arr1, ByVal arraddr, 2
CopyMemory arr2, ByVal arraddr + 2, 2
CopyMemory arr3, ByVal arraddr + 4, 2
List3.AddItem "arr(1)=" & arr1
List3.AddItem "arr(2)=" & arr2
List3.AddItem "arr(3)=" & arr3
'修改数组的值
CopyMemory ByVal arraddr, 13, 2
CopyMemory ByVal arraddr + 2, 28, 2
MsgBox "arr(1)=" & arr(1)
MsgBox "arr(2)=" & arr(2)
MsgBox "arr(3)=" & arr(3)
End Sub
'比如有一排连续的房间,每个房间都有一个编号,这个编号也是连续的。
'例如房间1、房间2、...房间n,这个n就是房间的编号,如果我对你说“请”到房间2
'拿一本书给我,那么你完成这个任务首先就是找到房间2,然后进入房间2拿到这本书。
'显而易见这个编号实际上就是地址
'那么,如果我们取得数组的首地址,那么我们就可以根据地址对数组进行各种操作。
'C语言提供了取得数组地址的语言特性,而VB则没有这样的语言特性,但我们依然可以
'通过API得到数组的地址。我们先来认识下这一个DLL--Msvbvm60.dll,这个是vb6.0
'的程序运行库,其就提供了一个可以获得数组地址的API,它的api声明如下:
Private Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" _
(ptr() As Any) As Long
'CopyMemory API请参照《VB指针教程1》,地址:http://bbs.bccn.net/thread-305122-1-1.html
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(Destination As Any, Source As Any, ByVal Length As Long)
Private Sub Form_Load()
Dim arr(1 To 3) As Integer
For i = 1 To 3
arr(i) = i * 10
Next
Dim arraddr As Long
'取得arr数组的首地址
arraddr = VarPtrArray(arr)
Dim arr1 As Integer, arr2 As Integer, arr3 As Integer
CopyMemory arr1, ByVal arraddr, 2
CopyMemory arr2, ByVal arraddr + 2, 2
CopyMemory arr3, ByVal arraddr + 4, 2
List1.AddItem "arr(1)=" & arr1
List1.AddItem "arr(2)=" & arr2
List1.AddItem "arr(3)=" & arr3
End Sub
'观察运行的结果,显然不是我们所预期的,为什么呢?这是因为VB数组的存储结构不同于我们先前所说的。
'VB数组的存储结构是使用一种叫做SafeArray的结构,而VarPtrArray(arr)取得的即是指向SafeArray结
'构的指针,我们现在得先去了解下SafeArray结构:
'Private Type SafeArray
' cDims As Integer '指向数组维数的指针
' fFeatures As Integer '用来描述数组如何分配和如何被释放的标志
' cbElements As Long '指向数组元素所占的字节数的指针
' cLocks As Long '一个计数器,用来跟踪该数组被锁定的次数
' pvData As Long '指向数组内一个元素的指针,最重要的部分
' cElements As Long '数组元素的个数
' lLbound As Long '数组的下限
'End Type
''以下是fFeatures的常量标志
'Private Const FADF_AUTO As Integer = &H1 '在堆栈中执行的分配
'Private Const FADF_STATIC As Integer = &H2 '静态分配
'Private Const FADF_EMBEDDED As Integer = &H4 '在结构中创建
'Private Const FADF_FIXEDSIZE As Integer = &H10 '不能改变数组大小
'Private Const FADF_RECORD As Integer = &H20 '记录容器
'Private Const FADF_HAVEIID As Integer = &H40 '有IID 身份标记 数组
'Private Const FADF_HAVEVARTYPE As Integer = &H80 'VT 类型数组
'Private Const FADF_BSTR As Integer = &H100 'BSTR数组
'Private Const FADF_UNKNOWN As Integer = &H200 'IUnknown* 数组
'Private Const FADF_DISPATCH As Integer = &H400 'IDispatch* 数组
'Private Const FADF_VARIANT As Integer = &H800 'VARIANTs数组
'Private Const FADF_RESERVED As Integer = &HF008 '余留,将来使用
Private Sub Command1_Click()
List2.Clear
List3.Clear
Dim arr(1 To 3) As Integer
For i = 1 To 3
arr(i) = i * 10
Next
'指向SafeArrayld结构的指针
Dim SafeArrayldPoint As Long
'把arr数组的首地址复制到SafeArrayldPoint
CopyMemory SafeArrayldPoint, ByVal VarPtrArray(arr), 4
'数组的维数
Dim dims As Integer
CopyMemory dims, ByVal SafeArrayldPoint, 2
List2.AddItem "数组的维数:" & dims
Dim elements As Long
CopyMemory elements, ByVal SafeArrayldPoint + 4, 4
List2.AddItem "数组元素所占的字节数:" & elements
Dim eCount As Long
CopyMemory eCount, ByVal SafeArrayldPoint + 16, 4
List2.AddItem "数组元素的个数:" & eCount
Dim lBd As Long
CopyMemory lBd, ByVal SafeArrayldPoint + 20, 4
List2.AddItem "数组的下限:" & lBd
'读取数组的值
Dim arraddr As Long
CopyMemory arraddr, ByVal SafeArrayldPoint + 12, 4
Dim arr1 As Integer, arr2 As Integer, arr3 As Integer
CopyMemory arr1, ByVal arraddr, 2
CopyMemory arr2, ByVal arraddr + 2, 2
CopyMemory arr3, ByVal arraddr + 4, 2
List3.AddItem "arr(1)=" & arr1
List3.AddItem "arr(2)=" & arr2
List3.AddItem "arr(3)=" & arr3
'修改数组的值
CopyMemory ByVal arraddr, 13, 2
CopyMemory ByVal arraddr + 2, 28, 2
MsgBox "arr(1)=" & arr(1)
MsgBox "arr(2)=" & arr(2)
MsgBox "arr(3)=" & arr(3)
End Sub
演示工程运行界面: