Often there are situations when you need to get data having only the address (for example, in WndProc, HookProc). Usually, simply copy the data via CopyMemory the structure after changing data and copy it back. If the structure is large, it will be a waste of resources to copy into structure and back. In languages such as C ++ is all done easily with the help of pointers, written something like newpos = (WINDOWPOS *) lparam. Nominally VB6 does not work with pointers, but there are a few workarounds.
Public Declare Function GetMem4 Lib "msvbvm60" (src As Any, Dst As Any) As Long
Public Declare Function ArrPtr Lib "msvbvm60" Alias "VarPtr" (src() As Any) As Long
For a start I will give the necessary declarations:
Code:
Private Type Vector
X As Single
Y As Single
End Type
Private Type TestRec
Name As String
Value As Long
Position As Vector
Money As Double
End Type
Private Sub Form_Load()
Dim tr As TestRec
Test tr
End Sub
Private Function Test(Pointer As TestRec, Optional ByVal nu As Long)
Dim q As TestRec, z As TestRec
q.Name = "The trick"
q.Position.X = 5: q.Position.Y = 15
q.Value = 12345: q.Money = 3.14
z.Name = "Visual Basic 6.0"
z.Position.X = 99: z.Position.Y = 105
z.Value = 7643: z.Money = 36.6
GetMem4 VarPtr(q), ByVal VarPtr(nu) - 4 ' Set pointer to q (Pointer = &q)
PrintRec Pointer
GetMem4 VarPtr(z), ByVal VarPtr(nu) - 4 ' Set pointer to z (Pointer = &z)
PrintRec Pointer
End Function
Private Sub PrintRec(Pt As TestRec)
Debug.Print "----------------"
Debug.Print "Name = " & Pt.Name
Debug.Print "Value = " & Pt.Value
Debug.Print "Money = " & Pt.Money
Debug.Print "Position.X = " & Pt.Position.X
Debug.Print "Position.Y = " & Pt.Position.Y
End Sub
You can also create a pointer by using arrays. The idea is to create 2 arrays one element each, which will store the address of a variable, and the other will refer to the data. The first will always be Long, a second type of data desired. This is useful for example if you want to pass on lists, etc. It's no secret that the array in VB is simply an SafeArray. In the data structure of this array contains a lot of useful information, and a pointer to the data. What we do, we create two arrays:
- 1st (with address) refers to a pointer to the second data array. As a result, changing the values in the first array, 2nd automatically refer to the desired data.*
- 2nd is directly the data pointed to by the first.*
Also, after all the manipulations necessary to return all the pointers back to VB properly clear the memory.* For all manipulations I created auxiliary functions and structure for data recovery.* Address SafeArray is available through Not Not Arr, but IDE after such manipulations are glitches with floating point:
Code:
Public Type PtDat
Prv1 As Long
Prv2 As Long
End Type
' Create the pointer. 1st param is pointer, 2nd address.
Public Function PtGet(Pointer() As Long, ByVal VarAddr As Long) As PtDat
Dim i As Long
i = GetSA(ArrPtr(Pointer)) + &HC
GetMem4 ByVal i, PtGet.Prv1
GetMem4 VarAddr + &HC, ByVal i
PtGet.Prv2 = Pointer(0)
End Function
' Release pointer
Public Sub PtRelease(Pointer() As Long, prev As PtDat)
Pointer(0) = prev.Prv2
GetMem4 prev.Prv1, ByVal GetSA(ArrPtr(Pointer)) + &HC
End Sub
' Obtaint address of SafeArray (same Not Not)
Public Function GetSA(ByVal addr As Long) As Long
GetMem4 ByVal addr, GetSA
End Function
Example of use:
Code:
Private Sub Form_Load()
Dim pt() As Long, var() As TestRec, prev As PtDat ' Pointer, references data, release data.
Dim q As TestRec, z As TestRec ' The structures, which we refer
ReDim pt(0): ReDim var(0)
q.Name = "The trick"
q.Position.X = 5: q.Position.Y = 15
q.Value = 12345: q.Money = 3.14
z.Name = "Visual Basic 6.0"
z.Position.X = 99: z.Position.Y = 105
z.Value = 7643: z.Money = 36.6
prev = PtGet(pt, GetSA(ArrPtr(var))) ' Create "pointer"
pt(0) = VarPtr(q) ' Refer to q (pt = &q)
PrintRec var(0)
pt(0) = VarPtr(z) ' Refer to z (pt = &z)
PrintRec var(0)
PtRelease pt, prev ' Release
End Sub
Source:
http://earlier189.rssing.com/browser.php?indx=6373759&item=376