Hallo,
Mir ist aufgefallen, das immer wieder Fragen gestellt werden, in denen Leute bei Fehlern im Zusammenhang mit Unicode nicht weiterkommen. Deshalb will ich hier kurz erläutern, wie man alle Fehler mit Unicode ganz einfach umgehen kann.
Zuerst will ich erwähnen, dass man Unicode beliebig in seinem Programm ein oder ausschalten kann. Das geht folgendermaßen:
Man geht auf Projekt/Eigenschaften/Konfigurationseigenschaften/Allgemein und wählt im Feld Zeichensatz entwerde Unicode oder Multi-Byte aus.
Man kann zwar alle Probleme mit Unicode aus der Welt schaffen, indem man Unicode einfach ausschaltet. Das das keine gute Lösung ist, kann man am besten anhand eines Beispiels erläutern:
Angenommen ihr wollt ein Programm schreiben. Dieses Programm soll zum einen in einer Sprache verfügbar sein, die die lateinischen Schriftzeichen verwendet (also Deutsch, Englisch, ...) und zum anderen in einer östlichen Sprache (z.B. Japanisch) die ein ganz anderes Alphabet von Schriftzeichen verwendet. Bei der Verwendung von Multi-Byte müsste man nun das Programm zweimal, nämlich unter einem Betriebssystem mit der einen und anschließend auf einem Betriebssystem mit der anderen Sprache kompilieren. Um dieses Problem zu umgehen verwendet man Unicode.
Außerdem beugt man viele Fehler vor, wenn man z.B. eine Engine so gestaltet, dass sie sowohl mit als auch ohne Unicode zurecht kommt.
Nun kommen wir zum ersten Problem.
Oft verzweifeln Leute an Fehlermeldungen à la
MessageBoxW: Konventierung des zweiten Parameters von LPCSTR in LPCWSTR nicht möglich
Diese Fehlermeldung liegt daran, dass Unicode-Zeichen (auch als breite Zeichen bezeichnet) viel mehr Speicher belegen, wie Multi-Byte Zeichen. Deshalb gibt es für Unicode spezielle Datentypen. Da es aber ein besserer Stil ist, Datentypen einzusetzen, die je nachdem, ob Unicode eingestellt ist oder nicht für Unicode oder Multi-Byte-Zeichen stehen. Diesen Datentyp gibt es nur für einzelne Schriftzeichen aber nicht für Strings er lautet:
|
C-/C++-Quelltext
|
1
|
TCHAR // steht bei eingestelltem Multi-Byte für char und bei eingestelltem Unicode für das Pendant wchar_t
|
Für Unicode-Strings gibt es die Datentypen:
PC
WSTR
LPC
WSTR
bei Multi-Byte sind das:
PCSTR
LPCSTR
Unicode Strings haben noch eine Besonderheit. Vor ihnen muss immer ein L stehen. Das sieht dann so aus:
|
C-/C++-Quelltext
|
1
|
L"Text"
|
bzw.:
|
C-/C++-Quelltext
|
1
|
L'Zeichen'
|
Folgender Code führt also bei eingestelltem Unicode zur obigen Fehlermeldung:
|
C-/C++-Quelltext
|
1
|
MessageBox(NULL, "Text", "Text", 0);
|
Wenn man nun ein L vor die Strings setzt, ist der Fehler behoben, aber wenn man nun Multi-Byte einstellt, kommt folgende Fehlermeldung:
MessageBoxA: Konventierung des Parameters 2 von LPCWSTR in LPCSTR nicht möglich
An dieser Stelle möchte ich noch kurz erwähnen, wofür das W und das A stehen, wenn man doch nur MessageBox benutzt hat. Das liegt daran, das MessageBox je nachdem ob Unicode definiert ist oder nicht Als MessageBoxA(Multi-Byte Version) oder MessageBoxW(Unicode-Version) definiert ist.
Hier kommmt nun ein Makro ins Spiel, das in WinDef.h definiert ist. Da WinDef.h von windows.h eingebunden wird, muss man also keine weiteren Headerdateien einbinden. Das Makro setzt je nachdem, ob Unicode Definiert ist ein L vor den String oder nicht. Das Makro wird wie folgt verwendet:
|
C-/C++-Quelltext
|
1
|
TEXT("Text")
|
Also muss man einfach immer, wenn eine Funktion eine Unicode und eine Multi-Byte Variante hat den Text über das Makro TEXT übergeben und schon ist man alle Probleme mit Unicode los und kann die Vorteile die der erweiterte Zeichensatz bietet in vollen Zügen ausnutzen.
Das Beispiel mit MessageBox würde dann wie folgt aussehen:
|
C-/C++-Quelltext
|
1
|
MessageBox(NULL, TEXT("Text"), TEXT("Text"), 0)
|
zugegeben, es ist Gewohnheitssache, aber es lohnt sich.