我有一个Excel VBA项目,我正在适应64位Office。在其中一部分,我调用了 MultiByteToWideChar()
使用20多个不同的代码页中的任何一个。(所以StrConv不是一个替代方案。)
多年来,我在32位Office中使用以下代码一直在工作 declare
:
Declare Function MultiByteToWideChar Lib "kernel32" ( _
ByVal codepage As Long, _
ByVal dwFlags As Long, _
lpMultiByteStr As Any, _
ByVal cbMultiByte As Long, _
ByVal lpWideCharStr As Long, _
ByVal cchWideChar As Long _
) As Long
'params: UINT, DWORD, LPCSTR, int, LPWSTR, int
'return: int
但我对64位的适应不是这样。我得到了错误的结果(例如,一个空字符串,而预期的是非空字符串),并经常崩溃。我使用的是一个 declare
我得到的 微软提供的Win32API_PtrSafe.TXT文件。. (当然,它可能有bug。)
所以,我猜测是声明语句或我的调用方式有问题。
下面是一个最小的示例,重现的。
'Windows API declarations
Public Const MB_PRECOMPOSED = &H1 'use precomposed chars
Declare PtrSafe Function MultiByteToWideChar Lib "kernel32" ( _
ByVal CodePage As Long, _
ByVal dwFlags As Long, _
ByVal lpMultiByteStr As String, _
ByVal cchMultiByte As Long, _
ByVal lpWideCharStr As String, _
ByVal cchWideChar As Long _
) As Long
'params: UINT, DWORD, LPCSTR, int, LPWSTR, int
'return: int
' My function that calls MultiByteToWideChar
Private Function EncodedStringByteArrayToString(abStringData() As Byte, lngArrLen As Long, CodePage As Long) As String
Dim lngStrLen As Long, str As String
lngStrLen = MultiByteToWideChar(CodePage, MB_PRECOMPOSED, ByVal VarPtr(abStringData(1)), lngArrLen, 0&, 0)
str = String(lngStrLen, " ")
lngStrLen = MultiByteToWideChar(CodePage, MB_PRECOMPOSED, ByVal VarPtr(abStringData(1)), lngArrLen, StrPtr(str), lngStrLen)
EncodedStringByteArrayToString = str
End Function
' Sample routine to produce repro
Private Sub TestMB2WCBug()
Dim abStringData(1 To 9) As Byte
Dim resultString As String
abStringData(1) = 67
abStringData(2) = 111
abStringData(3) = 112
abStringData(4) = 121
abStringData(5) = 114
abStringData(6) = 105
abStringData(7) = 103
abStringData(8) = 104
abStringData(9) = 116
resultString = EncodedStringByteArrayToString(abStringData(), 9, 10000)
End Sub
在32位的Office中,这对我来说已经工作了很多年。
它不可能与 Declare
你所展示的。
MultiByteToWideChar
期待一个 LPWSTR
作为输出缓冲区。当将字符串传递到 Declare
d函数,所以该函数不可能接收一个指向宽字符串缓冲区的指针,当 lpWideCharStr
被宣布为 As String
. 最多只能接收一个足够大的缓冲区,这样就不会发生缓冲区溢出的情况,然后VB会在从函数返回时执行转换回Unicode,所以你最终会得到一个双unicode字符串。
lpMultiByteStr
也不是一个字符串,它是一个字节数组,在 某种编码.
里面的代码 EncodedStringByteArrayToString
似乎知道所有这些,因为它正确地传递了一个字节数组给 lpMultiByteStr
和一个 StrPtr
对于 lpWideCharStr
. 在目前宣布的情况下,这种情况不可能发生。MultiByteToWideChar
.
中的代码所假设的声明。EncodedStringByteArrayToString
是。
Declare PtrSafe Function MultiByteToWideChar Lib "kernel32" ( _
ByVal CodePage As Long, _
ByVal dwFlags As Long, _
ByVal lpMultiByteStr As LongPtr, _
ByVal cchMultiByte As Long, _
ByVal lpWideCharStr As LongPtr, _
ByVal cchWideChar As Long _
) As Long
很明显,你以前有,所以把它放回去。