0xAA55 发表于 2014-6-1 17:32:50

【VB】VB6的指针操作

使用指针,不是为了去使用它而使用它,而是要合理地使用它。

1、调用API的时候传递指针参数的方法:
声明API的时候把该参数定义为“参数名 As Any”或“ByVal 参数名 As Long”。如果是前者,参数请直接填写变量名、数组元素或常数,这样VB6就会把变量的地址、数组元素的地址、常数的地址(这个常数被放到数据段,然后这里VB会自动获取它的地址)作为参数传递给API。如果是后者(即“ByVal 参数名 As Long”)那么调用的时候请把参数的地址传递给它(用VarPtr取地址)
举例:VB播放内存中的WAV文件数据。'声明:
Declare Function 播放WAV Lib "winmm.dll" Alias "sndPlaySoundA" (声音文件的指针 As Any, ByVal 标识 As Long) As Long
Const SND_MEMORY = &H4
Const SND_ASYNC = &H1
Global 声音文件的数据() As Byte '声音文件的内容

'初始化:
Sub LoadWAV() '载入WAV的子程序
Open "D:\A.WAV" For Binary Access Read As #1 '声音文件到内存
ReDim 声音文件的数据(LOF(1) - 1) '分配内存
Get #1, , 声音文件的数据 '一次性读取全部
Close #1
End Sub

'播放
Sub PlayWAV()
播放WAV 声音文件的数据(0), SND_MEMORY Or SND_ASYNC '传递数组第一个元素的地址
'因为是这样调用的,所以声明也可以是Declare Function 播放WAV Lib "winmm.dll" Alias "sndPlaySoundA" (声音文件的指针 As Byte, ByVal 标识 As Long) As Long
End Sub如果你需要传递NULL,并且参数的类型是Any,那么请直接使用vbNull即可。

2、自己内部使用指针的方法:
如果你是为了将一个结构体作为参数传递,那么请你相信:VB6会自动帮你传递结构体的指针,然后你的函数体内使用这个结构体的代码会被VB翻译成使用这个结构体指针的代码。
如果你是为了将一个数组作为参数传递的话,那么请你直接在定义函数的时候定义数组参数即可。如下:Sub 某过程(数组() As Byte) '字节数组
数组(0) = 233
End Sub3、VB取函数地址
用AddressOf。但是这个只能取Module里面的函数的地址。不能取Form和Class的成员函数的地址。例子请看这里

4、VB拷贝内存
直接用RtlMoveMemory即可。声明:Declare Sub RtlMoveMemory(Dest As Any, Src As Any, ByVal Len As Long)5、VB编写回调函数,参数列表的写法对应VC++的例子:
VB的“结构体 As 结构体类型”相当于VC++的“结构体类型 &结构体”
VB的“ByVal 长整型 As Long”相当于VC++的“long 长整形”
VB的“长整型 As Long”相当于VC++的“long &长整形”
VB的“数组() As 某类型”相当于VC++的“SAFEARRAY &数组”
当VC++想把一个字节数组传递给VB的时候,VB要这么声明:“ByVal 数组指针 As Long”或者“数组 As Byte(因为是字节数组) ”
然后VB只能通过RtlMoveMemory来控制整个数组。可以先内部用动态数组分配内存,然后用RtlMoveMemory来复制内容到自己的数组以便于操作,最后再用RtlMoveMemory把处理的结果复制出来(因此这样的程序最好不用VB写)
VB所有的函数都是_stdcall

6、VB的字符串数组
VB的String是字符串,它的存储结构是这样的:
4个字节的字符串长度在前。
后面是不定数量的Integer,这些Integer组成了UNICODE字符串,所谓UNICODE字符串的特点就是:无论什么字符,都占用两个字节。
有些API是以A结尾的(ANSI),有些API是以W结尾的(Wide),比如MessageBoxA和MessageBoxW。它们的区别就是A结尾的把字符串当做多字节字符串处理,而W结尾的则把字符串当做UNICODE处理。VB的String是UNICODE,那么VB应该调用哪个API呢?
答案是A结尾的API。因为VB会在调用API的时候自动转换字符串为多字节字符串,然后把字符串作为参数传递给API。API返回后,VB则会自动把得到的多字节字符串再转换成UNICODE返回。比如下面这样的代码:Declare Function MessageBoxA Lib "user32.dll" (ByVal hWnd&, ByVal 提示 As String, ByVal 标题 As String, ByVal 风格 As Long) As Long

'调用
Sub ShowMsg()
MessageBoxA 0, "我操这是提示", "API对话框", 0 '最后一个参数0就是MB_OK
End Sub虽然你调用的是MessageBoxA而不是MessageBoxW,而且给的参数就是VB的字符串(UNICODE编码),但是VB在背后帮你把它转换成ANSI然后传递给MessageBoxA,因此你会看到一个正常的对话框。
注意VB的""并不是NULL,而是一个长度为0的字符串(占用内存4字节)如果要把NULL传递给API请使用vbNullString,这东西相当于C、C++的NULL。
C、C++的'\0'相当于VB的vbNullChar

wypabcd 发表于 2014-12-21 07:14:44

vb学习中,非常有收获

cxx 发表于 2017-10-16 13:42:55

学习一下

xiawan 发表于 2022-5-10 14:47:19


啥也不说了,感谢楼主分享哇!
页: [1]
查看完整版本: 【VB】VB6的指针操作