VB与API学习笔记(2)Unicode与参数

一、Unicode

       vb6是以unicode为基础的,即双字节表示一字符。

       对于中文,两个字节中,高字节是大于128的字节。

       strconv(s,vbfromunicode)  表示是转为双字节与单节节混编,如果显示该串则是乱字符。

       要想重新显示“正确”的字符,就得再次转为Unicode或用字节数组显示。



二、参数

1、vbNullString

Private Sub Command1_Click()
    Print TypeName(vbNullString) 'string
    Print vbNullString = ""      'True
End Sub

    值为0的字符串,类同“”,但一般用于外部过程。在外部过程中会变成0&(长整形)

 VB与API学习笔记(2)Unicode与参数_第1张图片

上面是INI文件结构。三部分组成,由节(section),关键字(Key),值(String或Value)组成。

'仅对win.ini文件有效
Private Declare Function WriteProfileString Lib "kernel32" Alias "WriteProfileStringA" (ByVal lpszSection As String, ByVal lpszKeyName As String, ByVal lpszString As String) As Long

Private Sub Command1_Click()
    WriteProfileString "IniText", "Key01", "AnyValue" '写入值AnyValue
    WriteProfileString "IniText", "Key01", ""         '清除key01的值
    WriteProfileString "IniText", "Key01", vbNullString  '删除key01
    WriteProfileString "IniText", vbNullString, vbNullString  '删除IniText节
End Sub

    上面""与vbNullString的功效就出来了


'不加Private时,只能专对win.ini
'加了Private时,可以对自己的定义的Ini文件,文件名就是后面的lpFileName参数
'lpApplicationName就是Section
'lpKeyName就是Key,lpDefault是缺省值,lpReturnedString是取得值。nSize定义字串最大长度。
Private Declare Function WritePrivateProfileString _
                Lib "kernel32" _
                Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lpFileName As String) As Long

Private Declare Function GetPrivateProfileString _
                Lib "kernel32" _
                Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As Long

  同样,返回值为0不成功,非0成功。


  上面是操作字串,操作整数是:WritePrivateProfileInt

                                                          GetPrivateProfileInt

   操作节是:写入或读取节中所有关键字。

 Private Declare Function WritePrivateProfileSection Lib "kernel32" Alias "WritePrivateProfileSectionA" (ByVal lpAppName As String, ByVal lpString As String, ByVal lpFileName As String) As Long


Private Declare Function GetPrivateProfileSection Lib "kernel32" Alias "GetPrivateProfileSectionA" (ByVal lpAppName As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As Long

     关键字之间以chr(0)间隔,最后以chr(0)结束

     即:在节中按“key1=value"+chr(0)形式,把所有关键字串起来,最后以chr(0)结束,写入iNI文件中。


   上面参数Any,看似可以任何类型,但如果我们传入是Variant将会出错,因为这个任意对于这个API来说它只会认识两种 字串与长整形。


'限制鼠标在矩形框内活动
'矩形框是从左上角坐标到右下角坐标(自定义类型RECT)
Private Declare Function ClipCursor Lib "user32" (lpRect As Any) As Long

Private Type RECT
        Left As Long
        Top As Long
        Right As Long
        Bottom As Long
End Type

Private Sub Command1_Click()
    Dim r As RECT
    r.Left = 3
    r.Top = 3
    r.Right = 300
    r.Bottom = 300
    ClipCursor r
    
End Sub

Private Sub Command2_Click()
    ClipCursor ByVal 0&  '不能是0&,因为API是传址,若0&则传的是0处地址,此时应传0值来取消鼠标限制,故前加byval
End Sub



三、内容复制

      rtlmovememory  内存复制,就是从源块内存复制到目的块内存。

      它是一个可重叠的复制,即目的和源是可以有重叠的,如源块内存A到D可以复制到目的块内存C和F

VB与API学习笔记(2)Unicode与参数_第2张图片

   重叠复制不会影响目的内在的“变形”,那么它是怎么做的呢?,它会不会是把A-D先复制到下面黑块(另一区域)再把另一区域再复制到C到F呢?

    答案是否定的。当源地址小于目的地址时,它会从源块从高到低地复制到目的块。若源块大于目的块的地址,就会从源块从低地址到高地址复制到目的块中。

    这个不用纠结,因为这个被封装到了RtlMoveMemory中,它自动会处理。

     

    C:
语法  VOID RtlMoveMemory(VOID UNALIGNED *Destination,  //指向移动目的地址的指针。
                         const VOID UNALIGNED *Source,  //指向要复制的内存地址的指针。
                         SIZE_T Length               //指定要复制的字节数。
                        );
VB:
Declare Sub RtlMoveMemory Lib "kernel32"(Dest as any, Src as any, byval Length as long)

  

    注意:API对库名的大小写不敏感,对参数名也不敏感,但是对传递参数方式和返回值是严格的。

    下面最后一个参数是传值,是不能乱写的

Option Explicit
'复制内存块
Private Declare Sub RtlMoveMemory _
                Lib "kernel32" (Dest As Any, _
                                Src As Any, _
                                ByVal Length As Long)
'下面声明是错误的,会当掉VB程序。因为最后一个参数用的是址传递,API会认为是传递的地址而不是值
'Private Declare Sub RtlMoveMemory _
'                Lib "kernel32" (Dest As Any, _
'                                Src As Any, _
'                                Length As Long)
'
Private Type RECT
    Left As Long
    Top As Long
    Right As Long
    Bottom As Long
End Type

Private Sub Command1_Click()
    Dim r1 As RECT, r2 As RECT

    r1.Left = 30
    r1.Top = 40
    r1.Right = 500
    r1.Bottom = 600
    RtlMoveMemory r2, r1, 16 '复制,16字节大小
    Text1.Text = r2.Bottom
End Sub


下面是复制数据、字节,等操作:

Option Explicit

'注意这里变了一下形参,可以看出对API没有影响
Private Declare Sub RtlMoveMemory _
                Lib "kernel32" (d As Any, s As Any, ByVal size As Long)

Private Sub Command1_Click() '数组的复制
    Dim a(10) As Long, b(10) As Long
    Dim i     As Integer

    For i = 0 To 10
        a(i) = i
    Next i

    RtlMoveMemory b(0), a(0), Len(a(1)) * 11

    For i = 0 To 10
        List1.AddItem b(i)
    Next i

End Sub

Private Sub Command2_Click() '字符的复制
    Dim s1 As String, s2 As String

    s1 = "中英mixed"
    RtlMoveMemory s2, s1, LenB(s1) '这里不能用len,因为计算内存大小用字节,不是计算“字符”数
    Print s2
End Sub

Private Sub Command3_Click() '字节提取
    Dim a As Long, b(3) As Byte

    a = &H11223344  '16进制,这样表示可清晰看出内存中高低字节的值
    RtlMoveMemory b(0), a, 4
    Print Hex(b(0)) & "," & Hex(b(1)) & "," & Hex(b(2)) & "," & Hex(b(3))
    '44,33,22,11 可以看到低字节在索引0处,高字节在索引3处,和数据索引大小一一对应
    '这个功能对于我们破解软件做注册机,或者做外挂,是绝佳利器,不用什么转换,提取快,又清晰
    '后面的字节长度大小还可以自定,这样可以复制自己想要的部分,做大数运算是个不错的选择
End Sub


       









你可能感兴趣的:(api,unicode,vb)