[VC++] Cum folosesc seturi de caractere diferite?

Mediul de dezvoltare Visual C++, instalare, setari, debugger, compilator, linker si documentatie (forum moderat)
Post Reply
User avatar
Marius Bancila
Fondator
Fondator
Posts: 2344
Joined: 11 Jul 2007, 11:45
Judet: Timiş
Location: Timisoara
Contact:

[VC++] Cum folosesc seturi de caractere diferite?

Post by Marius Bancila » 30 Jul 2007, 13:26

Intrebare: Am urmatorul cod

Code: Select all

MessageBox(NULL, "Mesaj de test", "Titlu", MB_OK);
care imi genereaza o eroare de compilare.
error C2664: 'MessageBoxW' : cannot convert parameter 2 from 'const char [13]' to 'LPCWSTR'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
De ce?

Raspuns: Aceasta se intampla pentru ca proiectul este builduit pentru UNICODE. Biblioteca run-time de la Microsoft ofera mapari generice de text pentru multe functii si obiecte, definite in header-ul TCHAR.h. Exista 3 seturi de caractere suportate:
  • ASCII (single-byte character set – SBCS)
  • MBCS (multi-byte character set)
  • Unicode
Folosirea a unuia sau altuia e controlata de 2 definitii pre-procesor:
  • _UNICODE: daca e definit, setul folosit e Unicode
  • _MBCS: daca e definit, setul e MBCS
  • daca nici unul din cele 2 anterioare nu e definit, setul e ASCII

Intrebare: Cum selectez unul dintre aceste seturi?

Raspuns: Trebuie mers la Project Properties > Configuration Properties > General si modificata proprietatea Character Set. Optiunile disponibile sunt:
  • Not Set (nici _UNICODE si nici _MBCS nu sunt definite)
  • Use Multi-byte Character Set (_MBCS este definit)
  • Use Unicode Character Set (_UNICODE este definit)

Intrebare: Cum afecteaza aceste mapari de text functiile si structurile de date pe care le folosesc?

Raspuns: Functiile C runtime, precum _itot, sau functiile de Windows, precum MessageBox, nu sunt de fapt functii ci macrouri.

Biblioteca standard de C ofera functii pentru toate seturile de caractere si macrouri pentru selectia uneia sau alteia. De exemplu macro-ul _itot devine:
  • _itoa, cand _UNICODE nu e definit
  • _itow, cand _UNICODE este definit
In mod similar TCHAR devine:
  • char, cand _UNICODE nu e definit
  • wchar_t, cand _UNICODE este definit
Mai multe despre acestea pot fi citite in MSDN.

Pe de alta parte, majoritatea functiilor de Windows vin in doua variante: pentru Unicode si pentru ASCII/multi-byte. Pentru MessageBox in MSDN scrie ca:
The MessageBox function creates, displays, and operates a message box. The message box contains an application-defined message and title, plus any combination of predefined icons and push buttons.

Code: Select all

int MessageBox(
    HWND hWnd,
    LPCTSTR lpText,
    LPCTSTR lpCaption,
    UINT uType);
Insa de fapt, atat MessageBox cat si LPCTSTR sunt ambele macrouri. MessageBox este definit in Winuser.h

Code: Select all

WINUSERAPI
int
WINAPI
MessageBoxA(
    __in_opt HWND hWnd,
    __in_opt LPCSTR lpText,
    __in_opt LPCSTR lpCaption,
    __in UINT uType);
WINUSERAPI
int
WINAPI
MessageBoxW(
    __in_opt HWND hWnd,
    __in_opt LPCWSTR lpText,
    __in_opt LPCWSTR lpCaption,
    __in UINT uType);
#ifdef UNICODE
#define MessageBox  MessageBoxW
#else
#define MessageBox  MessageBoxA
#endif // !UNICODE

Intrebare: Cum scriu codul, astfel incat sa poata fi builduit pentru oricare dintre acestea?

Raspuns: Cand se foloseste setul single-byte sau multi-byte string-urile sau caracterele nu sunt prefixate de nimic (ex: "string", 'c'). Cand se foloseste Unicode, ele trebuie prefixate cu L (ex. L"string", L'c'). Macrourile specifice Microsoft _T() si TEXT() pot fi folosite pentru a genera automat aceste prefixuri (vid sau L), in functie de setul folosit. Atunci cand
  • _UNICODE nu e definit: _T("string") devine "string" si _T('c') devine 'c'
  • _UNICODE e definit: _T("string") devine L"string" si _T('c') devine L'c'
[/list]

Prin urmare, codul initial ar trebui scris asa:

Code: Select all

MessageBox(NULL, _T("Mesaj de test)", _T("Titlu"), MB_OK);


Marius Bancila
Fondator Codexpert, Microsoft MVP VC++
Site personal | Blog

Post Reply