找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 7265|回复: 3

【VB】VB6的指针操作

[复制链接]

1111

主题

1651

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
244
威望
743 点
宅币
24235 个
贡献
46222 次
宅之契约
0 份
在线时间
2296 小时
注册时间
2014-1-26
发表于 2014-6-1 17:32:50 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

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

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

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

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

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

4、VB拷贝内存
直接用RtlMoveMemory即可。声明:
  1. 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返回。比如下面这样的代码:
  1. Declare Function MessageBoxA Lib "user32.dll" (ByVal hWnd&, ByVal 提示 As String, ByVal 标题 As String, ByVal 风格 As Long) As Long

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

本帖被以下淘专辑推荐:

回复

使用道具 举报

0

主题

13

回帖

18

积分

用户组: 初·技术宅

UID
606
精华
0
威望
2 点
宅币
1 个
贡献
0 次
宅之契约
0 份
在线时间
0 小时
注册时间
2014-12-21
发表于 2014-12-21 07:14:44 | 显示全部楼层
vb学习中,非常有收获
回复 赞! 靠!

使用道具 举报

1

主题

14

回帖

15

积分

用户组: 初·技术宅

UID
2735
精华
0
威望
0 点
宅币
0 个
贡献
0 次
宅之契约
0 份
在线时间
6 小时
注册时间
2017-7-28
发表于 2017-10-16 13:42:55 | 显示全部楼层
学习一下
回复

使用道具 举报

1

主题

159

回帖

624

积分

用户组: 大·技术宅

UID
7535
精华
0
威望
0 点
宅币
464 个
贡献
0 次
宅之契约
0 份
在线时间
71 小时
注册时间
2021-10-16
发表于 2022-5-10 14:47:19 | 显示全部楼层

啥也不说了,感谢楼主分享哇!
回复 赞! 靠!

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-4-19 21:22 , Processed in 0.039828 second(s), 33 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表