升级建议:调整 Win32 API 的数据类型

更新:2007 年 11 月

许多 API 可以象在 Visual Basic 6.0 中那样被正确地使用,但是需要说明的是必须相应地调整数据类型。Visual Basic 6.0 Long 数据类型现在是 Visual Basic 2008Integer 数据类型,Visual Basic 6.0 Integer 数据类型现在是 Visual Basic 2008Short 数据类型。升级期间,这些更改将自动完成,简单的 API 与在 Visual Basic 6.0 中的工作方式完全相同。例如:

Private Declare Function GetVersion Lib "kernel32" () As Long
Function GetVer()
    Dim Ver As Long
    Ver = GetVersion()
    MsgBox ("System Version is " & Ver)
End Function

更改为:

Private Declare Function GetVersion Lib "kernel32" () As Integer
Function GetVer()
    Dim Ver As Integer
    Ver = GetVersion()
    MsgBox("System Version is " & Ver)
End Function

除了数值数据类型升级外,Visual Basic 6.0 还有一种 Visual Basic 2008 所不支持的定长串数据类型,该类型升级为定长串包装类。在 Visual Basic 6.0 中,经常可使用普通字符串执行相同的操作。例如:

Private Declare Function GetUserName Lib "advapi32.dll" Alias _
"GetUserNameA" (ByVal lpBuffer As String, ByRef nSize As Long) As Long
Function GetUser()
    Dim Ret As Long
    Dim UserName As String
    Dim Buffer As String * 25
    Ret = GetUserName(Buffer, 25)
    UserName = Left$(Buffer, InStr(Buffer, Chr(0)) - 1)
    MsgBox (UserName)
End Function

如果用显式设置为长度为 25 的普通字符串(而非定长串)来写,则效果更好:

Dim Buffer As String
Buffer = String$(25, " ")

升级到 Visual Basic 2008 后如下所示:

Declare Function GetUserName Lib "advapi32.dll" Alias _ 
"GetUserNameA" (ByVal lpBuffer As String, ByRef nSize As Integer) As Integer
Function GetUser()
    Dim Ret As Integer
    Dim UserName As String
    Dim Buffer As String
    Buffer = New String(CChar(" "), 25)
    Ret = GetUserName(Buffer, 25)
    UserName = Left(Buffer, InStr(Buffer, Chr(0)) - 1)
    MsgBox(UserName)
End Function

因为可以选择使用 ANSI 和 UNICODE 关键字来声明字符串的传递方式,所以在某些情况下,Visual Basic 2008 可更好地处理向 API 传递字符串的操作。

有三种可能需要进行一些更改的情况。第一种情况是向 API 传递包含定长串或字节数组的用户定义类型时。在 Visual Basic 2008 中可能需要更改代码,方法是向用户定义类型的每个定长串或字节数组添加 MarshallAs 属性(来自 System.Runtime.InteropServices 命名空间)。第二种情况是在 Declare 语句中使用 As Any 变量类型时。Visual Basic 2008 中不支持。As Any 类型的变量通常用于传递字符串或 Null 变量;可以通过声明两种格式的 API(一种接受长型,另一种接受字符串)替换此 Visual Basic 6.0 的用法。例如,GetPrivateProfileString API 具有一个 As Any 类型的 lpKeyName 参数:

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

可通过用两种版本替换 Declare 来去除“As Any”,其中一种版本接受长型,另一种版本接受字符串:

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

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

如果希望将 Null 值传递给 API,则应使用 GetPrivateProfileStringNullKey 版本。这样做意味着将函数升级到 Visual Basic 2008。

最后一种需要做些更改的情况是在使用进行下列操作的 API 时:执行线程创建,从 Windows 类派生和执行消息对列挂钩等。其中的某些函数将在 Visual Basic 2008 中引起运行时错误。许多这类 API 在 Visual Basic 2008 或 .NET Framework 中具有等效项。必须逐一修复这些函数。

请参见

其他资源

有关升级的语言建议