Hallo,
ich musste meine Frage in 2 Beiträge aufteilen (den 2. Teil sende ich als Antwort), da der Text sonst zu lang wäre.
Teil1:
Ich programmiere seit einiger Zeit an einem Internet-basiertes Informationssystem für ein Spiel (Disneys Toontown Online) unter dem Namen "Toontown WebInfo".
Dies funktioniert folgendermaßen:
Die Benutzer laden sich das Programm herunter und legen ein Konto an. Dann verbindet sich der Client mit meinem Server (auf dem eine Server-Version des Programms läuft) über eine TCP-Verbindung mit Winsock. Der Client liest kontinuierlich die Logdateien, die das Spiel erzeugt, aus, wertet diese aus und schickt relevante Informationen an den Server, der dann u. a. eine Grafik mit diesen Informationen erzeugt und eine "Invasionstabelle" verwaltet.
Dies funktioniert bis jetzt recht gut.
Nun gibt es auch eine japanische Version dieses Spiels. VB6 hat seine Strings zwar im Unicode-Format (UTF-16 Little Endian), aber es ist ja bekannt, dass die VB6-Standardsteuerelemente (Label, Text usw.) keine Unicode-Zeichen darstellen können, die außerhalb des lokalen ANSI-Zeichensatzes liegen. Beispielsweise wird bei Label1.Caption = ChrW(65411) statt eines japanischen Zeichens ein Fragezeichen angezeigt.
Dieses Problem konnte ich soweit lösen, indem ich mir mit der TextOutW-Variante der TextOut() API-Funktion als unicodefähige Alternative zur VB-eigenen Print-Funktion einen unicodefähigen Label bastelte, der solche Zeichen korrekt anzeigt (z. B. auf einem deutschen/englischen Windows). Die unicodefähigen Varianten für die TextWidth()- und TextHeight()-Funktionen konnte ich mit der GetTextExtentPoint32W-Variante der GetTextExtentPoint32() API-Funktion nachbauen. Die Logdatei wird im UTF-8-Format gespeichert, also schrieb ich auch eine Funktion, die UTF-8 in UTF-16 LE konvertiert.
Nun aber zum eigentlichen Problem.
Wenn das Programm die japanische Version des Spiels unterstützt, sollte es natürlich auch auf einem japanischen Windows laufen. Also habe ich ein (deutsches) Windows installiert und in den Ländereinstellungen bei "Regionale Einstellungen" und bei Erweitert für den lokalen ANSI-Zeichensatz "Japanisch" ausgewählt. Und plötzlich ging in dem Programm überhaupt nichts mehr (es konnte keine Daten über Winsock mehr richtig empfangen (es schien als wären bestimmte Bytes "verschwunden"), und das Auslesen der Logdatei brachte ganz andere Ergebnisse als erwartet).
Nach einiger Fehlersuche fand ich raus, dass VB auf einem japanischen Windows anscheinend Probleme (Bug oder Feature?) mit Strings hat, die Bytewerte > 127 enthalten (nicht den Unicode-Wert, sondern den ANSI-Wert).
Wenn ich folgendes auf einem deutschen Windows schreibe:
MsgBox Asc(Chr(135)) erscheint in der MsgBox "135", wie erwartet. Auf einem japanischen Windows dagegen 0! Wie kann das denn sein?
Doch nicht nur, dass solche mit Chr() erzeugten Zeichen den Wert 0 haben. Wenn ich folgendermaßen eine Datei in einen String einlese, die Bytes mit solchen Werten besitzt:
Dim EinleseString As String, BytesBereitsEingelesen As Long
Open "C:\Datei.log" For Binary Access Read Shared As 1
Seek 1, BytesBereitsEingelesen + 1
EinleseString = String(LOF(1) - BytesBereitsEingelesen, "x")
Get 1, , EinleseString
Close 1 dann "verschwinden" diese Stellen im fertigen String. Doch die Zeichen fehlen nicht einfach, sondern es wird anscheinend im Unicode-String wie beim Manipulieren mit den Byte-basierten Stringfunktionen (z. B. MidB()) irgendwas verändert, und nach einer solchen Stelle erscheinen irgendwelche chinesischen Zeichen.
Ich habe dieses Problem gelöst, indem ich zum Auslesen der Datei einfach die Byte-basierten String-Funktionen benutze (z. B. MidB, ChrB, LenB, InstrB usw). Denn wenn ich MsgBox AscB(ChrB(135)) schreibe, dann zeigt es auch 135 an. Da es keine InStrRevB-Funktion gibt (nur InStrB), habe ich mir die schnell nachreiben müssen. Ich lese die Datei in ein Byte-Array ein und weise dieses dann einen String zu, sodass diese Stringvariable dann keinen Unicode-String enthält.
Wenn ich jetzt z. b. schauen will, wo der Text "Text" in der Datei vorkommt, mache ich dies mit
Pos = InStrB(1, sVar, StrConv("Text", vbFromUnicode) Das Problem, dass jetzt immer noch besteht, ist, dass ich für den unicodefähigen Label, der die TextOutW Funktion benutzt, den zu übergebenden String wieder nach Unicode konvertieren muss.
Bitte den 2. Teil lesen (Antwort). |