WideCharToMultiByte в QB64

У меня проблемы с преобразованием из 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

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) не будет работать, как задумано, не то, что любой из MultiByteToWideChar или же WideCharToMultiByte требуется нулевой ввод (вот почему byteCount а также ccWideChar параметры существуют; иногда вы хотите оперировать только частью строки).

Хуже, даже если вы используете _MEMFILL установить все байты Filename на 0, чтобы позволить вам иметь дело с вещами, используя строки ASCIIZ, INPUT а также LINE INPUT заполнит все оставшиеся байты, явно не введенные в Filename с 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)

...
Другие вопросы по тегам