【问题标题】:WideCharToMultiByte in QB64QB64 中的 WideCharToMultiByte
【发布时间】:2017-09-06 02:31:06
【问题描述】:

在从 ANSI 转换为 Unicode 再转换回来时遇到问题。以下代码片段描述了我在做什么。我收到 0x57 错误..

DECLARE DYNAMIC LIBRARY "kernel32"
    FUNCTION MultiByteToWideChar& (codePage~&, dwFlags~&, lpszMbstring$, byteCount&, lpwszWcstring$, wideCount&)
    FUNCTION WideCharToMultiByte& (codePage~&, dwFlags~&, lpWideString$, BYVAL ccWideChar%, lpMultiByte$, BYVAL multibyte%, BYVAL defaultchar&, BYVAL usedchar&)
    FUNCTION GetLastError& ()
END DECLARE
DIM Filename AS STRING * 260, NewFilename AS STRING * 260, MultiByte AS STRING * 260
PRINT "Enter filename";: INPUT Filename$: 'Filename$ = Filename$ + CHR$(0)
x = MultiByteToWideChar(0, 0, Filename$, LEN(Filename$), NewFilename$, 260)
IF x = 0 THEN
    PRINT "Error 0x"; HEX$(GetLastError)
ELSE
    PRINT "Processing: "; NewFilename$
END IF
' do unicode stuff here
x = WideCharToMultiByte(65001, 0, NewFilename$, LEN(NewFilename$), MultiByte$, 0, 0, 0)
' display processed filename
IF x = 0 THEN
    PRINT "Error 0x"; HEX$(GetLastError)
ELSE
    PRINT MultiByte$
END IF

【问题讨论】:

    标签: basic qbasic qb64


    【解决方案1】:

    需要使用 BYVAL 关键字传递更多参数:

    FUNCTION MultiByteToWideChar& (BYVAL codePage~&, BYVAL dwFlags~&, lpszMbstring$, BYVAL byteCount&, lpwszWcstring$, BYVAL wideCount&)
    FUNCTION WideCharToMultiByte& (BYVAL codePage~&, BYVAL dwFlags~&, lpWideString$, BYVAL ccWideChar%, lpMultiByte$, BYVAL multibyte%, BYVAL defaultchar&, BYVAL usedchar&)
    

    除此之外,STRING * 260 的长度始终为 260,与存储的任何值无关。这意味着 Filename = Filename + CHR$(0) 不会按预期工作,而不是 MultiByteToWideCharWideCharToMultiByte 需要以空值结尾的输入(这就是存在 byteCountccWideChar 参数的原因;有时您只想在字符串的一部分)。

    更糟糕的是,即使您使用 _MEMFILLFilename 的所有字节设置为 0 以允许您使用 ASCIIZ 字符串处理事物,INPUTLINE INPUT 将填充任何未明确输入到 @ 中的剩余字节987654333@ 和 CHR$(32)(即一个空格,就像您按下了空格键一样)。例如,如果您输入“Hello”,则输入的字符串将有 5 个字节和 255 个字节的字符代码 32(或 &H20,如果您更喜欢十六进制)。

    为了避免让自己头疼(“hello world.bas”是一个有效的文件名!),您需要使用STRING,而不是STRING * 260。如果长度大于 260,您可能应该打印一条错误消息。之后是否允许用户输入新文件名取决于您。

    您还需要使用MultiByteToWideChar 的返回值,因为它是NewFilename 中的字符数:

    DIM Filename AS STRING
    DIM NewFilename AS STRING * 260
    DIM MultiByte AS STRING * 260
    ...
    
    ' Note: LEN(NewFilename) = 260 (**always**)
    ' This is why the number of wide chars written
    ' is saved.
    NewFilenameLen = MultiByteToWideChar(0, 0, Filename, LEN(Filename), NewFilename, LEN(NewFilename))
    
    ...
    
    ' Note: LEN(MultiByte) = 260 (**always**)
    x = WideCharToMultiByte(65001, 0, NewFilename, NewFilenameLen, MultiByte, LEN(MultiByte), 0, 0)
    
    ...
    

    【讨论】:

    • 好的,再次感谢。当我将所有代码拼凑在一起时,这应该会做一段时间..
    • 文档声明 DOS 8.3 格式的文件名将在 cAlternateFilename 中,除非 cFilename 已经是 8.3 文件名,在这种情况下 cAlternateFilename 是一个空字符串。例如,foo.txt 会产生一个空的cAlternateFilename 成员,而HelloWorld.txtfoo.config 可能会产生HelloW~1.txtfoo~7.con
    • 如果文件具有长文件名,则完整名称出现在cFileName 成员中,而名称的8.3 格式截断版本出现在cAlternateFileName 成员中。否则,cAlternateFileName 为空。 - 来自WIN32_FIND_DATA structure docs 的“备注”部分
    • .cAlternateFilename 未正确返回的原因是因为 Win32_Find_DataW 中的 .cFilename 必须为 520 字节才能支持扩展 ASCIIZ 的 2 字节对。
    • @eoredson 啊,是的。我想我已经习惯了使用基于 Unicode 的wchar_t 进行 Windows 和 Linux C 编程。如果我用得够多,我会分叉 QB64 并添加对 Unicode 字符串的支持,但我几乎从不使用它,除了运行一些 QuickBASIC 代码。好收获
    猜你喜欢
    • 2011-03-23
    • 2011-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-10
    相关资源
    最近更新 更多