I would want some clarifications concerning this code (that explain how
to fill an array with a bitmap - you can find the original at
http://herman.eldering.net/vb/cpymemgf.htm):
'DECLARATIONS
--------------------------------------------------
Private Type SAFEARRAYBOUND
cElements As Long
lLbound As Long
End Type
Private Type SAFEARRAY1D
cDims As Integer
fFeatures As Integer
cbElements As Long
cLocks As Long
pvData As Long
Bounds(0 To 0) As SAFEARRAYBOUND
End Type
Private Type SAFEARRAY2D
cDims As Integer
fFeatures As Integer
cbElements As Long
cLocks As Long
pvData As Long
Bounds(0 To 1) As SAFEARRAYBOUND
End Type
Private Declare Function VarPtrArray Lib "msvbvm50.dll" Alias "VarPtr"
(Ptr() As Any) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory"
(pDst As Any, pSrc As Any, ByVal ByteLen As Long)
Private Type BITMAP
bmType As Long
bmWidth As Long
bmHeight As Long
bmWidthBytes As Long
bmPlanes As Integer
bmBitsPixel As Integer
bmBits As Long
End Type
Private Declare Function GetObjectAPI Lib "gdi32" Alias "GetObjectA"
(ByVal hObject As Long, ByVal nCount As Long, lpObject As Any) As Long
--------------------------------------------------
'THIS IS THE CODE
--------------------------------------------------
Dim sa As SAFEARRAY2D, bmp As BITMAP
Dim r As Integer, c As Integer
' get bitmap info
GetObjectAPI Pictbox.Picture, Len(bmp), bmp
' exit if not a supported bitmap
If bmp.bmPlanes <> 1 Or bmp.bmBitsPixel <> 8 Then
MsgBox " 256-color bitmaps only", vbCritical
Exit Sub
End If
' have the local matrix point to bitmap pixels
With sa
.cbElements = 1
.cDims = 2
.Bounds(0).lLbound = 0
.Bounds(0).cElements = bmp.bmHeight
.Bounds(1).lLbound = 0
.Bounds(1).cElements = bmp.bmWidthBytes
.pvData = bmp.bmBits
End With
CopyMemory ByVal VarPtrArray(pict), VarPtr(sa), 4
'Go through the entire array
For c = 1 To UBound(pict, 1) - 1
For r = 1 To UBound(pict, 2)
'Assign new values to the array
pict(c, r) = NewValue
Next
Next
' clear the temporary array descriptor
' without destroying the local temporary array
CopyMemory ByVal VarPtrArray(pict), 0&, 4
' inform VB that something has changed
Pictbox.Refresh
--------------------------------------------------
Could you explain me exactly what do the CopyMemory in this case?
Why the image is copied in the array?
I hope you can help me, thank you.
(excuse me for my bad english)
--
Roberto
email: ron...@tiscalinet.it
Sent via Deja.com http://www.deja.com/
Before you buy.
The image isn't copied into the pict array. (The declaration for pict is
missing from the quoted code)
VB arrays are defined by an underlying SafeArray structure. When an array
is dimensioned a memory location stores the address of the array. This
address is actually the address of the start of the SafeArray structure
that defines the array.
Perhaps a diagram could clarify this. The actual numbers shown are made
up and different every time.
Dim MyArray(1) as Byte produces this:
At address -> 8385320
----------------
| 6478172 |<------ The address of the start of the
---------------- SafeArray structure that defines
MyArray
The SafeArray structure defines, among other things, the number of array
dimensions, the Lower Bound of the array, the size of array elements, and
yet another address (pvData) that is the start address of the actual
array data.
Declaring an array without dimensioning it e.g. Dim MyArray() As Byte
doesn't create an array. It can't do because the array has no dimensions,
bound, or actual array data so a SafeArray structure describing the array
isn't created. What happens is that the "address" for the non-existent
SafeArray is set to 0
Dim MyArray() as Byte produces this:
At address -> 8385320
----------------
| 0 |
----------------
One can define an array not by declaring it in VB but by creating a home-
brew SafeArray structure and filling out the structure elements to
describe the kind of array one wants. The clever part is that the array
data pointer pvData can be set to point to the bitmap data for a bitmap,
or anything else one wants to manipulate.
So in the code you quote this sets up a home-brewed SafeArray:
With sa
.cbElements = 1
.cDims = 2
.Bounds(0).lLbound = 0
.Bounds(0).cElements = bmp.bmHeight
.Bounds(1).lLbound = 0
.Bounds(1).cElements = bmp.bmWidthBytes
.pvData = bmp.bmBits
End With
And this sets up the address for the home-brewed SafeArray:
CopyMemory ByVal VarPtrArray(pict), VarPtr(sa), 4
and one would now have:
At address -> 8385320
----------------
| 37E5724 |<------ The address of the start of the
---------------- home-brewed SafeArray structure
that defines MyArray
VB, of course, knows nothing about this sleight of hand so when one is
finished one uses this:
CopyMemory ByVal VarPtrArray(pict), 0&, 4
to get back to this:
At address -> 8385320
----------------
| 0 |
----------------
The above technique was first described in the October 1997 issue of
Visual Basic Programmers Journal.
"Write Faster Apps with VB Pointers" by Matthew Curland and Francesco
Balena.
The point of using this technique is increase speed, but many apps won't
see any noticable difference from just getting the data bytes into a
conventionally defined array. In fact if the object is speed the For Next
array access in the quoted code is the wrong way round.
--
Richard Mason