2017-09-06 9 views
0

J'ai des problèmes de conversion d'ANSI en Unicode et vice versa. Le code suivant décrit ce que je fais. Je reçois 0x57 erreurs ..WideCharToMultiByte dans QB64

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 

Répondre

1

Certains plus args doivent être passés avec le mot-clé 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&) 

En dehors de cela, la longueur de STRING * 260 est toujours 260, indépendamment de toute valeur stockée . Cela signifie que Filename = Filename + CHR$(0) ne fonctionnera pas comme prévu, pas que MultiByteToWideChar ou WideCharToMultiByte nécessitent une entrée à terminaison nulle (c'est la raison pour laquelle les paramètres byteCount et ccWideChar existent, parfois vous ne voulez utiliser qu'une partie d'une chaîne).

Pire encore, même si vous utilisez _MEMFILL pour définir tous les octets de Filename-0 pour vous permettre de traiter des choses en utilisant des chaînes de ASCIIZ, INPUT et LINE INPUT remplira tous les octets restants ne figurant pas dans explicitement Filename avec CHR$(32) (ie un espace vide comme si vous avez appuyé sur la barre d'espace). Par exemple, si vous entrez "Bonjour", il y aurait 5 octets pour la chaîne entrée et 255 octets pour le code 32 (ou &H20 si vous préférez hexadécimal).

Pour vous sauver ce mal de tête terrible ("bonjour world.bas" est un nom de fichier valide!), Vous aurez besoin d'utiliser STRING, pas STRING * 260. Si la longueur est supérieure à 260, vous devez probablement imprimer un message d'erreur. Que vous autorisiez un utilisateur à entrer un nouveau nom de fichier ou non, c'est à vous de décider.

Vous aurez également d'utiliser la valeur de retour de MultiByteToWideChar puisqu'il est le nombre de caractères dans 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) 

... 
+0

Ok, merci encore. Cela devrait à peu près le faire pendant un certain temps que je rassemble tout le code. – eoredson

+0

BTW: Pourquoi FindFirstFileW retourne .cAlternateFilename comme NUL? – eoredson

+1

Les docs indiquent qu'un nom de fichier au format DOS 8.3 sera dans 'cAlternateFilename' sauf si' cFilename' est déjà un nom de fichier 8.3, auquel cas 'cAlternateFilename' est une chaîne vide. Par exemple, 'foo.txt' résulterait en un membre' cAlternateFilename' vide alors que 'HelloWorld.txt' et' foo.config' pourraient donner 'HelloW ~ 1.txt' et' foo ~ 7.con'. –