|
2#
楼主 |
发表于 2015-6-13 10:55:44
|
只看该作者
本帖最后由 ganlinlao 于 2015-6-15 11:47 编辑
1、在鸡窝前,我永远站在蛋的这一边----vba内部的数据类型。
无论你多么的不熟悉VBA,只要你开始学习VBA,毫无疑问,数据类型,可能会是你首先学习的第一个内容。事实上,你可能会轻易地略过数据类型的字节(没印象了吧?),甚至会很疑惑,为什么要强调数据类型的字节。
但涉及到指针操作,数据类型的字节变得非常重要。一旦字节搞错了,后果很严重。
以下是VBA常用的数据类型和字节:
类型 | byte | Boolen | Integer | Long | Single | Double | Currency | Decimal | Date | String | Variant | Object | LongLong | 字节 | 1字节 | 2字节
| 2 字节 | 4 字节 | 4 字节 | 8 字节 | 8 字节 | 12 字节 | 8 字节 | 4字节 | 16字节 | 4字节
| 8字节 | 注:Decimal因为只能包含在Variant中,所以我个人理解应该是16字节。指针intptr都是4字节,在vba中也可以用long表示。
看起来数据类型很是不少。有意思的是,在msvbvm60.dll中,它没有这些概念,它只有mem1,mem2,mem4,mem8对应的是1字节,2字节,4字节,8字节,至于Arrary数组和Variant都是一种特殊的结构。真是让人大吃一惊。
*******************************************************
接下来部分是msvbvm60.tlb中的函数说明
********************************************************
内存操作:
Sub CopyBytes(Length As SizeT, Destination As Any, Source As Any)
移动指定长度的字节流
Sub CopyBytesZero(Length As SizeT, Destination As Any, Source As Any)
移动指定长度的字节流,并清零
Sub MoveBytes(Destination As Any, Source As Any, Length As SizeT)
安全拷贝指定长度的字节流
Sub CopyMem1(Source As Any, Destination As Any)
拷贝任意变量1字节值
Sub CopyMem2(Source As Any, Destination As Any)
拷贝任意变量2字节值
Sub CopyMem4(Source As Any, Destination As Any)
拷贝任意变量4字节值
Sub CopyMem8(Source As Any, Destination As Any)
拷贝任意变量8字节值
Sub CopyMemArr(Destination As IntPtr, Source As IntPtr)
拷贝内存数组结构
Sub CopyMemObj(Source As Any, Destination As Any)
拷贝任意变量引用
Sub CopyMemPtr(Source As Any, Destination As Any)
拷贝任意变量指针长度值
Sub CopyMemVar(Source As Any, Destination As Any)
拷贝任意变量变体值
Sub CopyMemVars(Destination As IntPtr, Source As IntPtr)
拷贝数组内存值
FunPtr(Address As IntPtr) As IntPtr
返回一个函数或过程的地址。必须配合addressof。但因为addressof 只能对标准模块中的函数有用,
而且vb无法在内部使用函数指针,所以这个意义变得不大
GetLen(StringAddress As IntPtr)
根据字符串地址获取长度
GetLenB(StringAddress As IntPtr)
根据字符串地址获取字节数
sub GetMem1(Address As IntPtr, Value As Any)
读取内存1字节值
Sub GetMem2(Address As IntPtr, Value As Any)
Sub GetMem4(Address As IntPtr, Value As Any)
Sub GetMem8(Address As IntPtr, Value As Any)
Sub GetMemArr(Value() As Any, Address As IntPtr)
Sub GetMemObj(Address As IntPtr, Value As Any)
Sub GetMemPtr(Address As IntPtr, Value As Any)
Sub GetMemStr(Address As IntPtr, Value As Any)
Sub GetMemVars(Value() As Any, Address As IntPtr)
GetPtrObj(Address As IntPtr) As Object
GetPtrStr(Address As IntPtr) As String
Function GetRetStr(Address As IntPtr) As String
返回一个临时字符串,并自动析构字符串
ObjPtr(Object As Unknown) As IntPtr
ObjPtrEx(Object As Unknown) As IntPtr
VarMove(LeftValue, RightValue)
从一个变体移到另一个变体
VarPtr(Expression As Any) As IntPtr
返回一个变量的地址或一个常量的临时地址
PtrBool(Address As IntPtr) As Boolean
指针取值
PtrByte(Address As IntPtr) As Byte
PtrCur(Address As IntPtr) As Currency
PtrDate(Address As IntPtr) As Date
PtrDbl(Address As IntPtr) As Double
PtrInt(Address As IntPtr) As Integer
PtrLng(Address As IntPtr) As Long
PtrObj(Address As IntPtr) As Object
PtrPtr(Address As IntPtr) As IntPtr
PtrSng(Address As IntPtr) As Single
PtrStr(Address As IntPtr) As String
PtrVar(Address As IntPtr)
设置或返回一个内存地址所指向的variant值
Sub PutMem1(Address As IntPtr, Value As Any)
写入内存1字节的值
Sub PutMem2(Address As IntPtr, Value As Any)
Sub PutMem4(Address As IntPtr, Value As Any)
Sub PutMem8(Address As IntPtr, Value As Any)
Sub PutMemObj(Address As IntPtr, Value As Any)
Sub PutMemPtr(Address As IntPtr, Value As Any)
Sub PutMemStr(Address As IntPtr, Value As Any)
Sub PutMemVar(Address As IntPtr, Value As Any)
Sub PutMemVars(Address As IntPtr, Value() As Any)
SetMemObj(Address As IntPtr, Value As Any)
SetMemVar(Address As IntPtr, Value As Any)
为方便使用API,合并数字类型:
MakeWord(LoByte As Byte, HiByte As Byte, [_Invalid As Byte]) As Integer
两个字节合成一个字值
MakeDWordLong(LoDWord As Long, HiDWord As Long, [_Invalid As LongLong]) As LongLong
两个双字合成一个四字值
SplitDWord(DWord As Long) As DWord
SplitDWordLong(DWordLong As LongLong) As DWordLong
SplitRGB(Color As ColorConstants) As ColorRGBA
SplitWord(Word As Integer) As Word
说明:假乎漏了一个MakeDword
字符串处理:
StrMove(LeftValue As String, RightValue As String)
StrPtr(String As String) As IntPtr
StrPtrEx(String As String) As IntPtr
StrToAnsi(Destination As String) As String
StrToUnicode(Destination As String) As String
AllocStr(String As Any) As String
以C风格unicode字符串创建vb6字符串(vbnullChar结束)
AllocStrLen(String As Any, Length As SizeT) As String
以C风格unicode字符串创建vb6字符串(字符数)
AllocStrLenB(String As Any, LenBits As SizeT) As String
以C风格unicode字符串创建vb6字符串(字节数)
数组处理:
ArrPtr(Array() As Any) As IntPtr
返回一个数组结构的内存地址
VarsPtr(Array() As Any) As IntPtr
返回一个数组变量的内存地址
AccessData(ArrayAddress As IntPtr) As IntPtr
锁定并返回数组的数据地址
ArrDim(ArrayAddress As IntPtr) As SizeT
返回数组维数
ArrStruct(ArrayAddress As IntPtr) As SafeArray
返回数组结构
ArrType(ArrayAddress As IntPtr) As VbVarType
返回数组的元素类型
Elemsize(ArrayAddress As IntPtr) As SizeT
返回数组元素大小
Sub ArrMove(LeftValue() As Any, RightValue() As Any)
从一个数组移动到另一个数组
GetLBound(ArrayAddress As IntPtr, [Dim As SizeT = vbByteSize]) As Long
返回数组的索引下限
GetUBound(ArrayAddress As IntPtr, [Dim As SizeT = vbByteSize]) As Long
返回数组的索引上限
UnaccessData(ArrayAddress As IntPtr)
解锁并结束数组的数据地址
ArrIID(ArrayAddress As IntPtr) As UUID
设置或返回数组的接口UUID
RandomUUID
随机生成一个UUID,并返回数组的索引下界
StringUUID(lpsz As String) As UUID
将string形式转成UUID,并返回数组的索引下界
图片处理:
LoadPicture(FileName, [WidthDesired As Long], [HeightDesired As Long], [Flags As LoadPictureConstants]) As StdPicture
从文件中加载图片
LoadStmPicture(Stream As IStream, Size As SizeT, Runmode As BOOLAPI, IID As UUID) As StdPicture
从流中加载一张图片
NewPicture(PICTDESC As PICTDESC, IID As UUID, [Own As BOOLAPI]) As StdPicture
创建新的图片
SavePicture(Picture As StdPicture, FileName As String)
保存图片到文件中
内存管理:
AllocMem(Bytes As SizeT) As IntPtr
分配指定大小的内存
FreeMem(Address As IntPtr)
释放内存
Malloc([MemMode As MallocMode = vbTaskMalloc]) As IMalloc
返回内存管理对象
ReallocMem(Address As IntPtr, Bytes As SizeT) As IntPtr
重分配指定大小的内存
一些API拓展:
Sub Beep2([Sound As VbMsgBoxStyle])
播放系统提示音
Beep3(Freq As Long, Duration As Long)
播放指定频率和时间的蜂鸣声
Clock() As Long
获得运行时间
FillBytes(Destination As Any, Length As SizeT, Fill As Byte)
填充指定长度的字节流
MoveBytes(Destination As Any, Source As Any, Length As SizeT)
安全拷贝指定长度的字节流
Sleep(MilliSeconds As Long)
暂停当前线程,毫秒为单位
Sub WaitEvents()
等待当前线程的事件产生,与Doevents相反
ZeroBytes(Destination As Any, Length As SizeT)
清空指定长度的字节流
HLSToRGB(Hue As Integer, Luminance As Integer, Saturation As Integer) As ColorConstants
HLs颜色转RGB颜色
Sub RGBToHLS(RGB As ColorConstants, Hue As Integer, Luminance As Integer, Saturation As Integer)
SHfunction拓展:
Sub AtomicUnknownRelease([ppunk As Any])
Function QueryUnknownService(punk As Unknown, Service As UUID, IID As UUID) As Unknown
Sub SetUnknown(ppunk As Unknown, [punk As Unknown])
Property SetUnknownSite(punk As Unknown) As Unknown
Property UnknownSite(punk As Unknown, [riid As UUID]) As Unknown
Property UnknownWindow(punk As Unknown) As OLE_HANDLE
字节流处理:
Sub CopyStream(pstmFrom As IStream, pstmTo As IStream, cb As SizeT)
Property CreateMemStream(Init As Byte, Size As SizeT) As IStream
从内存创建流
Property CreateStream(FileName As String, [Mode As StreamMode], [Attributes As Long], [Create As BOOLAPI], [Template As IStream]) As IStream
Sub MakeHash(Data As Any, DataSize As SizeT, Hash As Any, HashSize As SizeT)
Sub ReadStream(pstm As IStream, pv As Any, cb As SizeT)
Sub ReadStreamStr(pstm As IStream, ppsz As String)
Sub ResetStream(pstm As IStream)
Property StreamSize(pstm As IStream, pui As LongLong)
Sub WriteStream(pstm As IStream, pv As Any, cb As SizeT)
Sub WriteStreamStr(pstm As IStream, psz As String)
说明1:在使用copyMem*,getMem*,putMem*等函数时,你一定要非常清楚自己在做什么。
这些函数都不做类型安全检查。所以字节大小有没有匹配变得很重要。如果不匹配,编辑器不会提示类型溢出,但结果很可能是错误的。
这些函数都比普通的“=”赋值,性能要快。因为它省掉了很多步骤。
说明2:小心定长数组和定长字符串,它们在作为参数传递的时候,vb会强制把它们转成动态数组和动态字符串,也就是说vb会自动生成一个临时变量。这时候varsptr或strptr获得的地址都是这个临时变量的地址,而不是真正的定长数组和定长字符串的地址。(vb的坑真不少呀)
|
|