Cordes. TCHAR LPWCS LPCTSTR CSsortingng. Quoi de quoi ici, simple rapide

TCHAR szExeFileName[MAX_PATH]; GetModuleFileName(NULL, szExeFileName, MAX_PATH); CSsortingng tmp; lstrcpy(szExeFileName, tmp); CSsortingng out; out.Format("\nInstall32 at %s\n", tmp); TRACE(tmp); 

Erreur (au format):

 error C2664: 'void ATL::CSsortingngT::Format(const wchar_t *,...)' : cannot convert parameter 1 from 'const char [15]' to 'const wchar_t 

Je voudrais juste obtenir le chemin actuel à partir duquel ce programme a été lancé et le copier dans un CSsortingng afin que je puisse l’utiliser ailleurs. Je suis juste en train d’essayer de voir le chemin en le TRACE. Mais les chaînes, les caractères, les tableaux de caractères, je ne peux jamais obtenir tout le détroit. Quelqu’un pourrait-il me donner un pointeur?

Je suppose que vous comstackz en mode Unicode.

Essayez de placer votre chaîne de format dans la macro _T, conçue pour fournir une méthode toujours correcte permettant de fournir des parameters de chaîne constants, que vous compiliez en mode Unicode ou ANSI:

 out.Format(_T("\nInstall32 at %s\n"), tmp); 

La réponse acceptée aborde le problème. Mais la question demandait également une meilleure compréhension des différences entre tous les types de caractères sous Windows.

Codages

Un caractère sous Windows (et pratiquement tous les autres systèmes) est un octet unique. Un octet est généralement interprété comme une valeur non signée [0..255] ou une valeur signée [-128..127]. (Les anciennes normes C ++ garantissent une plage signée de seulement [-127..127], mais la plupart des implémentations donnent [-128..127]. Je pense que C ++ 11 garantit une plage plus étendue.)

ASCII est un mappage de caractères pour les valeurs comsockets entre [0..127] et des caractères particuliers. Vous pouvez donc stocker un caractère ASCII dans un octet signé ou non signé, de sorte qu’il entre toujours dans un caractère.

Mais l’ASCII n’ayant pas tous les caractères nécessaires pour la plupart des langues, les jeux de caractères ont souvent été étendus en utilisant le rest des valeurs disponibles dans un octet pour représenter les caractères supplémentaires nécessaires pour certaines langues (ou familles de langues). Ainsi, alors que [0..127] signifie presque toujours la même chose, des valeurs telles que 150 ne peuvent être interprétées que dans le contexte d’un codage particulier. Pour les alphabets à un octet, ces codages sont appelés pages de code.

Les pages de code ont aidé, mais elles n’ont pas résolu tous les problèmes. Il fallait toujours savoir quelle page de code un document particulier était utilisé pour pouvoir l’interpréter correctement. De plus, vous ne pouvez généralement pas écrire un seul document dans différentes langues.

De plus, certaines langues ont plus de 256 caractères, il était donc impossible de mapper un caractère à un caractère. Cela a conduit au développement de codages de caractères multi-octets, où [0..127] est toujours ASCII, mais certaines des autres valeurs sont des “échappements”, ce qui signifie que vous devez regarder un certain nombre de caractères suivants pour comprendre ce que personnage que vous avez vraiment eu. (Il est préférable de penser à plusieurs octets en tant que variable , car certains caractères ne requièrent qu’un octet tandis que d’autres en exigent deux ou plus.) Les travaux sur plusieurs octets, mais c’est une tâche ardue pour le code.

Pendant ce temps, la mémoire devenait de plus en plus abondante, ce qui a amené un groupe d’organisations à créer Unicode, dans le but de mapper de manière universelle les valeurs aux caractères (pour des définitions suffisamment vagues de “caractères”). Au départ, on pensait que tous les caractères (ou du moins ceux que quiconque utiliserait) entreraient dans les valeurs 16 bits, ce qui était bien, car vous n’auriez pas à traiter avec des codages sur plusieurs octets. utilisez deux octets par caractère au lieu d’un. À peu près à la même époque, Microsoft a décidé d’adopter Unicode comme représentation interne du texte dans Windows.

WCHAR

Donc, Windows a un type appelé WCHAR , une valeur sur deux octets qui représente un “caractère” “Unicode”. J’utilise des guillemets ici car Unicode a évolué après le codage à deux octets d’origine. Ce que Windows appelle “Unicode” n’est pas vraiment Unicode aujourd’hui – il s’agit en fait d’un codage Unicode appelé UTF-16. Et un “caractère” n’est pas un concept aussi simple en Unicode qu’en ASCII, car, dans certaines langues, les caractères se combinent ou influencent les caractères adjacents de manière intéressante.

Les versions plus récentes de Windows utilisaient ces valeurs WCHAR 16 bits pour le texte en interne, mais il restait encore beaucoup de code écrit pour les pages de codes à un octet, et même certains pour les codages à plusieurs octets. Ces programmes utilisaient toujours des caractères plutôt que des WCHAR . Et beaucoup de ces programmes ont dû travailler avec des personnes utilisant des versions antérieures de Windows qui utilisaient toujours des caractères internes, ainsi que des versions plus récentes utilisant WCHAR . Ainsi, une technique utilisant des macros C et des typedefs a été conçue pour que vous puissiez principalement écrire votre code dans un sens et – au moment de la compilation – choisir de l’utiliser soit avec char soit avec WCHAR .

TCHAR

Pour accomplir cette flexibilité, vous utilisez un TCHAR pour un “caractère de texte”. Dans certains fichiers d’en-tête (souvent ), TCHAR serait typé en fonction de char ou de WCHAR , en fonction de l’environnement de compilation. Les en-têtes Windows ont adopté des conventions comme celle-ci:

  • LPTSTR est un pointeur (long) sur une chaîne de caractères TCHAR .
  • LPWSTR est un pointeur (long) sur une chaîne de WCHAR .
  • LPSTR est un pointeur (long) sur une chaîne de caractères.

(Le L pour “long” est un reliquat des jours 16 bits, lorsque nous avions des pointeurs longs, lointains et proches. Ceux-ci sont tous obsolètes aujourd’hui, mais le préfixe L tendance à restr.)

La plupart des fonctions de l’API Windows prenant et renvoyant des chaînes ont été remplacées par deux versions: la version A (pour les caractères “ANSI”) et la version W (pour les caractères larges). (Encore une fois, les inheritances historiques y figurent. Le schéma de pages de code s’appelait souvent des pages de code ANSI, même si je n’ai jamais précisé si elles étaient réellement régies par les normes ANSI.)

Donc, quand vous appelez une API Windows comme ceci:

 SetWindowText(hwnd, lptszTitle); 

vous faites en réalité appel à une macro de préprocesseur qui se développe en SetWindowTextA ou SetWindowTextW . Cela devrait être conforme à la TCHAR . Autrement dit, si vous voulez des chaînes de caractères, vous aurez la version A , et si vous voulez des chaînes de WCHAR , vous obtenez la version W

Mais c’est un peu plus compliqué à cause des littéraux de chaîne. Si vous écrivez ceci:

 SetWindowText(hwnd, "Hello World"); // works only in "ANSI" mode 

alors cela ne comstackra que si vous ciblez la version du caractère, parce que "Hello World" est une chaîne de caractères, il est donc uniquement compatible avec la version de SetWindowTextA . Si vous vouliez la version WCHAR , vous devriez écrire:

 SetWindowText(hwnd, L"Hello World"); // only works in "Unicode" mode 

Le L ici signifie que vous voulez des caractères larges. (Le L signifie long, mais son sens est différent de celui des pointeurs longs ci-dessus.) Lorsque le compilateur voit le préfixe L sur la chaîne, il sait que cette chaîne doit être codée sous la forme d’une série de wchar_t s plutôt que de caractères char .

(Les compilateurs ciblant Windows utilisent une valeur de deux octets pour wchar_t , ce qui est identique à ce que Windows a défini comme WCHAR . Les compilateurs ciblant d’autres systèmes utilisent souvent une valeur de quatre octets pour wchar_t , ce qui est vraiment nécessaire pour contenir un seul code Unicode. sharepoint code.)

Donc, si vous voulez un code qui peut être compilé de toute façon, vous avez besoin d’une autre macro pour envelopper les littéraux de chaîne. Vous _T() choisir parmi deux _T() : _T() et TEXT() . Ils fonctionnent exactement de la même manière. Le premier provient de la bibliothèque du compilateur et le second des bibliothèques du système d’exploitation. Donc, vous écrivez votre code comme ceci:

 SetWindowText(hwnd, TEXT("Hello World")); // comstacks in either mode 

Si vous ciblez des caractères, la macro est une option qui ne renvoie que le littéral de chaîne normal. Si vous ciblez les WCHAR , la macro ajoute le L .

Alors, comment dites-vous au compilateur que vous souhaitez cibler WCHAR ? Vous définissez UNICODE et _UNICODE . Le premier est destiné aux API Windows et le dernier aux bibliothèques du compilateur. Assurez-vous de ne jamais définir l’un sans l’autre.