This is similar to the way a union works in C or C++. It works by applying custom settings to a SAFEARRAY structure (aka safe array descriptor). I've done a lot of commenting on the code, so others can see exactly how it works.
Below is the code for the module, which contains the Windows API declarations part of the program.
And here's the code for Form1. It contains the body of the program's code.
Note that you need to set the AutoRedraw property of Form1 to True, in order for the output text to actually display (otherwise it gets cleared before the form displays on the screen).
If you have everything set up correctly, when you run the program you should see these 4 lines of text printed on the form.
12
34
56
78
Below is the code for the module, which contains the Windows API declarations part of the program.
Code:
Public Declare Sub PutMem4 Lib "msvbvm60.dll" (ByRef Destination As Any, ByVal Source As Long)
Public Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (ByRef ptr() As Any) As Long
Public Type SAFEARRAYBOUND
NumberOfElements As Long
FirstElementIndex As Long
End Type
Public Type SAFEARRAY
VariantType As Long 'This is actually at offset = -4 in the structure.
cDims As Integer 'THIS is the official start of the structure (offset = 0).
fFeatures As Integer
cbElements As Long
cLocks As Long
pvData As Long
Dim1Info As SAFEARRAYBOUND
End Type
And here's the code for Form1. It contains the body of the program's code.
Code:
Private Sub Form_Load()
Dim MyLong As Long
Dim MyArrayDescriptor As SAFEARRAY
Dim ptrMyArrayDescriptor() As Byte
'Set up the array descriptor so that the array will be a bytewise representation of the MyLong variable.
With MyArrayDescriptor
.VariantType = vbByte 'Data type is byte, and this is how the program would set it if using Redim to initialize the array, though programs written in VB6 actually ignore this field when reading the structure, and instead use the type originally set in the Dim statement when defining the array variable.
.cDims = 1 'Number of dimensions.
.cbElements = 1 'Number of bytes per element.
.fFeatures = &H80 'Tell it to use the VariantType field, though this is actually ignored when VB6 programs read the descriptor in VB6 programs. I just set it like this because this is how VB6 programs set it as well if using Redim to initialize the array.
.Dim1Info.NumberOfElements = 4
.pvData = VarPtr(MyLong) 'This makes the array refer to the same location in memory as the MyLong variable.
End With
'Activate the array descriptor by pointing the ptrMyArrayDescriptor variable to the actual array descriptor.
PutMem4 ByVal VarPtrArray(ptrMyArrayDescriptor), VarPtr(MyArrayDescriptor.cDims)
'Set the MyLong variable to a large value that covers all 4 of its bytes.
MyLong = &H12345678
'Indepndantly print the value of each of the variable's 4 bytes, in hexadecimal format.
Print Hex$(ptrMyArrayDescriptor(3))
Print Hex$(ptrMyArrayDescriptor(2))
Print Hex$(ptrMyArrayDescriptor(1))
Print Hex$(ptrMyArrayDescriptor(0))
PutMem4 ByVal VarPtrArray(ptrMyArrayDescriptor), 0
'This last line of code deactivates the pointer to the safe array descriptor, by setting the pointer to 0.
'This is needed to prevent the program from automatically attempting to deallocate both the descriptor and array content from memory.
'VB6 automatically inserts code after the end of each function to clean up memory, by deallocating arrays that have gone out of scope.
'This is normally good. As normally these would be allocated to the heap, or other system assigned memory location, when using Windows API functions to create a safe array.
'However in this example, this memory is allocated to the stack by the variables called MyLong and MyArrayDescriptor.
'The result is that the automatic array cleanup could corrupt the stack. Therefore manually setting this pointer to 0 is needed.
'The stack itself is cleaned up when the function ends.
'In fact, if the stack got corrupted as previously mentioned, the stack cleanup would likely make the program unstable or even crash immediately.
End Sub
If you have everything set up correctly, when you run the program you should see these 4 lines of text printed on the form.
Quote:
12
34
56
78