à quoi ressemblent LPCTSTR
et LPCTSTR
(par exemple HDC
) et ce que cela signifie?
Citant Brian Kramer sur les forums MSDN
LPCTSTR
= [~ # ~] l [~ # ~] ong [~ # ~ ] p [~ # ~] pointeur vers un [~ # ~] c [~ # ~] onst [~ # ~] t [~ # ~] CHAR [~ # ~] str [~ # ~] ing (Ne vous inquiétez pas, un long pointeur est identique à un pointeur. Il y avait deux versions de pointeurs sous des fenêtres 16 bits.)Voici le tableau:
LPSTR
=char*
LPCSTR
=const char*
LPWSTR
=wchar_t*
LPCWSTR
=const wchar_t*
LPTSTR
=char* or wchar_t*
cela dépend de_UNICODE
LPCTSTR
=const char* or const wchar_t*
cela dépend de_UNICODE
Il n'est pas nécessaire d'utiliser les types relatifs à TCHAR.
Ces types, tous les types de structure qui les utilisent et toutes les fonctions associées sont mappés au moment de la compilation sur une version ANSI ou UNICODE (en fonction de la configuration de votre projet). Les versions ANSI ont généralement un A ajouté à la fin du nom, et les versions Unicode ajoutent un W. Vous pouvez les utiliser explicitement si vous préférez. MSDN le notera si nécessaire, par exemple, il répertorie une fonction MessageBoxIndirectA et MessageBoxIndirectW ici: http://msdn.Microsoft.com/en-us/library/windows/desktop/ms645511 (v = vs.85) .aspx
À moins que vous ne cibliez Windows 9x, qui manquait d'implémentations de nombreuses fonctions Unicode, il n'est pas nécessaire d'utiliser les versions ANSI. Si vous ciblez Windows 9x, vous pouvez utiliser TCHAR pour créer un binaire ansi et unicode à partir de la même base de code, tant que votre code ne fait aucune hypothèse quant à savoir si TCHAR est un char ou un wchar.
Si vous ne vous souciez pas de Windows 9x, je vous recommande de configurer votre projet comme unicode et de traiter TCHAR comme identique à WCHAR. Vous pouvez utiliser explicitement les fonctions et types W si vous préférez, mais tant que vous ne prévoyez pas d'exécuter votre projet sur Windows 9x, cela n'a pas vraiment d'importance.
Ces types sont documentés à Windows Data Types sur MSDN:
LPCTSTR
Un
LPCWSTR
siUNICODE
est défini, unLPCSTR
sinon. Pour plus d'informations, consultez Types de données Windows pour les chaînes.Ce type est déclaré dans WinNT.h comme suit:
#ifdef UNICODE typedef LPCWSTR LPCTSTR; #else typedef LPCSTR LPCTSTR; #endif
LPCWSTR
Pointeur vers une chaîne constante terminée par un caractère nul de caractères Unicode 16 bits. Pour plus d'informations, voir Jeux de caractères utilisés par les polices.
Ce type est déclaré dans WinNT.h comme suit:
typedef CONST WCHAR *LPCWSTR;
HDC
Un handle vers un contexte de périphérique (DC).
Ce type est déclaré dans WinDef.h comme suit:
typedef HANDLE HDC;
Je sais que cette question a été posée il y a un certain temps et je n'essaie pas de répondre directement à la question d'origine exacte, mais comme ce Q/A particulier a une note décente, je voudrais ajouter un peu ici pour les futurs lecteurs. Cela concerne plus spécifiquement le Win32
API
typedefs
et comment les comprendre.
Si quelqu'un a déjà fait de la programmation Windows à l'époque des machines 32 bits de Windows 95 à Windows 7-8, il comprend et sait que le Win32
API
est chargé avec typedefs
et qu'une majorité de leurs fonctions et structures qui doivent être remplies et utilisées en dépendent fortement.
Voici un programme de base pour Windows à titre de démonstration.
#include <Windows.h>
HWND ghMainWnd = 0;
bool InitWindowsApp( HINSTANCE, int show );
LRESULT CALLBACK WindowProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam );
int run();
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int show ) {
if ( !InitWindowsApp( hInstance, showCmd ) ) {
return 0;
}
return run();
}
LRESULT CALLBACK WindowProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam ) {
switch( msg ) {
case WM_KEYDOWN: {
if ( wParam == VK_ESCAPE ) {
DestroyWindow( ghMainWnd );
}
return 0;
}
case WM_DESTROY: {
PostQuitMessage(0);
return 0;
}
default: {
return DefWindowProc( hWnd, msg, wParam, lParam );
}
}
}
bool InitWindowsApp( HINSTANCE hInstance, int nCmdShow ) {
WNDCLASSEX wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.cbClsExtra = NULL;
wc.cbWndExtra = NULL;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wc.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.lpszMenuName = NULL;
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszClassName = L"Basic Window";
wc.cbSize = sizeof( WNDCLASSEX);
if ( !RegisterClassEx( &wc ) ) {
MessageBox( NULL, L"Register Class FAILED", NULL, NULL );
return false;
}
ghMainWnd = CreateWindow(
L"Basic Window",
L"Win32Basic",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL, NULL,
hInstance,
NULL );
if ( ghMainWnd == 0 ) {
MessageBox( NULL, L"Window failed to create", L"Error", MB_OK );
return false;
}
ShowWindow( ghMainWnd, nCmdShow );
UpdateWindow( ghMainWnd );
return true;
}
int run() {
MSG msg = {0};
BOOL bReturn = 1;
while( (bReturn = GetMessage( &msg, NULL, NULL, NULL)) != 0 ) {
if ( bReturn == -1 ) {
MessageBox( NULL, L"GetMessage FAILED", L"Error", MB_OK );
break;
} else {
TranslateMessage( &msg );
DispatchMessage( &msg );
}
}
return (int)msg.wParam;
}
C'est à peine assez de code pour rendre une application Windows. C'est la configuration la plus basique pour initialiser les propriétés minimales nues pour rendre une fenêtre de base et comme vous pouvez le voir, elle est déjà chargée avec typedefs
à partir de Win32
api
.
Décomposons-le en regardant les fonctions WinMain
et InitWindowsApp
: La première chose est les paramètres des fonctions HINSTANCE
et PSTR
:
WinMain
accepte un seul objet HINSTANCE
tandis que InitWindowsApp
accepte deux objets HINSTANCE
un objet PSTR ou une autre chaîne typedef
et un int.
J'utiliserai ici la fonction InitWindowsApp
car elle donnera une description de l'objet dans les deux fonctions.
Le premier HINSTANCE
est défini comme un [~ # ~] h [~ # ~] andle à un [~ # ~] instance [~ # ~] et c'est celle qui est la plus utilisée pour l'application. Le second est un autre HANDLE
vers une instance précédente [~ # ~] [~ # ~] qui est rarement utilisée. Il a été conservé à des fins héritées afin de ne pas avoir à modifier la signature de fonction WinMain()
qui casserait de nombreuses applications déjà existantes dans le processus. Le troisième paramètre est un [~ # ~] p [~ # ~] ointer vers un [~ # ~ ] str [~ # ~] ing.
Nous devons donc nous demander ce qu'est un HANDLE
? Si nous regardons dans les documents Win32
API
trouvés ici: Windows Data Types nous pouvons facilement le rechercher et voir qu'il est défini comme:
Une poignée à un objet. Ce type est déclaré dans WinNT.h comme suit:
typedef PVOID HANDLE;
Nous avons maintenant un autre typedef
. Qu'est-ce qu'un PVOID
? Eh bien, cela devrait être évident, mais regardons cela dans le même tableau ...
Un pointeur vers n'importe quel type. Ceci est déclaré dans WinNT.h
typedef void *PVOID;
Un HANDLE
est utilisé pour déclarer de nombreux objets dans les éléments Win32
API
tels que:
HKEY
- Un handle vers une clé de registre. Déclaré dans WinDef.h typdef HANDLE HKEY;
HKL
- Un handle vers un identificateur de paramètres régionaux. Déclaré dans WinDef.h typdef HANDLE HKL;
HMENU
- Un handle vers un menu. Déclaré dans WinDef.h typdef HANDLE HMENU;
HPEN
- Une poignée pour un stylo. Déclaré dans WinDef.h typedef HANDLE HPEN;
HWND
- Un handle vers une fenêtre. Déclaré dans WinDef.h typedef HANDLE HWND;
HBRUSH
, HCURSOR
, HBITMAP
, HDC
, HDESK
, etc.Ce sont tous typedefs
qui sont déclarés à l'aide d'un typedef
qui est un HANDLE
et le HANDLE
lui-même est déclaré comme un typedef
à partir d'un PVOID
qui est aussi un typedef
vers un void pointer
.
Donc, quand il s'agit de LPCTSTR
, nous pouvons trouver que dans les mêmes documents:
Il est défini comme un
LPCWSTR
siUNICODE
est défini ou unLPCSTR
sinon.
#ifdef UNICODE
typedef LPCWSTR LPCSTR;
#else
typedef LPCSTR LPCTSTR;
#endif
J'espère donc que cela vous aidera à comprendre comment utiliser typedefs
en particulier avec les Types de données Windows que vous pouvez trouver dans le Win32
API
.