Public Type SAFEARRAY2
    cDims As Integer         '这个数组有几维?
    fFeatures As Integer     '这个数组有什么特性?
    cbElements As Long       '数组的每个元素有多大?
    cLocks As Long           '这个数组被锁定过几次?
    pvData As Long           '这个数组里的数据放在什么地方?
    CE0 As Long              '这一维有多少个元素?
    LB0 As Long              '它的索引从几开始?
    CE1 As Long
    LB1 As Long
End Type
'使一个数组指向数据
Function MapArray(ByRef a As Variant) As Long
'cause it was uncommented, I decided to. (gonchuki)
'ok, this is documented in the original app but i don't
'use that function here :-P
'Original comment as follows:
    ' ...very useful function of my DIB-Helper class. MapArray fools VB
    ' making him think that his array (which is not bounded, in fact)
    ' is mapped to particular space in memory (DIB bits in our case).
    ' it returns byte-width of one line of pixels in DIB
'so what it does is return a linear array whit the color information of each pixel
'but be careful!!! each pixel is converted to three (RGB) bytes and the DIB is upside-down
'and what we have in memory is the last pixel at the beggining and in the format BGR    sa.cDims = 1
    sa.cbElements = 1
    sa.pvData = mPtr
    sa.CE0 = mBmpInfoHeader.biSizeImage
    CopyMemory saPtr, ByVal VarPtr(a) + 8, 4  '把变量a的内存地址+8到变量a的内存地址+12之间的数据拷贝到数据saPtr中
    CopyMemory ByVal saPtr, VarPtr(sa), 4
    MapArray = mBmpInfoHeader.biSizeImage \ mBmpInfoHeader.biHeight
End Function
这个函数的作用看了半天都不明白,那位能稍微解释下,
主要是这
    CopyMemory saPtr, ByVal VarPtr(a) + 8, 4 
    CopyMemory ByVal saPtr, VarPtr(sa), 4
两句,为什么第一个copymemory中的VarPtr(a)要加8,以及他的工作原理如果 Dim SrcBytes() As Byte
然后执行
MapArray SrcBytes
SrcBytes这个数组中就有数据了,怎么搞的呢?

解决方案 »

  1.   

    a是variant类型,variant类型是个结构型的数据结构,偏移量8的位置上所在的4字节数据就是该variant类型的值或指向值的指针。在这里,我想a应该是个数组变量
    CopyMemory saPtr, ByVal VarPtr(a) + 8, 4 的作用是将存放a数组地址的地址取出来赋给saPtr变量
    CopyMemory ByVal saPtr, VarPtr(sa), 4 的作用是将sa数组的地址存放到上面取出来的地址很拗口,但其实所做的事情却很简单,就是将我们自己构造的数组sa放到变体类型a里,然后我们就可以直接通过a来访问所构造的数组sa了。
      

  2.   

    绿豆写得够细了,我再加点详细的:
    首先你要明白存储数组的机制,VB数组传递的实际上也是一个Long指针(为表述方便,暂称它为“数组结构指针”),但这个指针并不是指向数组中的首个元素,而是SAFEARRAY结构,这个结构上面有定义,它的pvData成员才是直正指向数组首个元素的指针,你算一下就知道,它前面有两个Integer成员与两个Long成员,它的位置就是结构偏移2+2+4+4=12个Byte。
    包含一数组的 Variant 比单独的一个数组需要多 12 个字节。这12个字节中的最后4个字节,就是指向“数组结构指针”的指针,两个Copy的目的就是为了修改“数组结构指针”,我们要分两步走:
    1、要获取Variant中保存的指针,VarPtr(a)取得Variant地址,它偏称8字节后的4个字节就是指向“数组结构指针”的指针,第一个Copy就是取出这4个字节,放入saPtr;2、saPtr所指向的内存地址存放着数组结构指针,我们要把这个指针,改成指向我们自己新建的这个结构,就要修改这个指针的值,第二个Copy就是用VarPtr(sa)取得我们结构的地址值,替换 saPtr所指向地址中所存的那个值(前面说过,那是数组结构指针);表述得很累,不知说清楚没有?这里是用Variant来取得“数组结构指针”,有一定安全隐患,因为Variant在保存不同数据时结构与长度也是不同的,若传入的不是数组,程序可能会挂掉。我们还可声明下面函数
    Declare Function VarPtrArray Lib "msvbvm60.dll" Alias "VarPtr" (Var() As Any) As Long
    用它可直接取得“数组结构指针”。下面说说我的看法:
    1、对SAFEARRAY结构的这个乾坤大挪移之法,被很多人所推崇,在采用DIB处理位图时,可以省去申请内存,拷出数组及拷入数组等几个步骤,在数组比较大时,的确可提高不少速度。不过,相对于处理位图时逐像素循环运算而言,这种提高却几乎可忽略不计。相反会增加复杂性,降低可靠性与可读性。
    2、单独就图像处理而言,这种方法只适合DIB方式处理,因为内建DIB时使用的是VB自己的数据数组;对于基于DDB的位图处理,它就用不上了。而实际应用中,若不是位图文件转换,位图的输入与输出都是DDB,基于DDB的处理总是快于DIB的,因为无论是DDB传入DIB,还是DIB传入DDB都会很慢,这一进一出,常常比图像处理循环本身还要耗时,所以基于DDB做图像处理是提速的一个更有效的方法,尤其是处理只用于显示或预览的位图时。不过处理DDB也有缺点,那就是设备相关性,必需针对所有可能位图位深格式写出相应的处理过程,至少要包括8、16、24、32位四种格式。
      

  3.   

    楼主去看一下那个"超熊"写的 VB葵花宝典就知道怎么回事了,主要是关于在VB中如何通过指针来操作数组的,在数据量很大的情况下可以提高数组运算的速度。
      

  4.   

    今天看了一天了,这些问题都弄明白了,确实速度快了很多,真是厉害zyl910!