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 FunctionExample 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
No comments:
Post a Comment