czym jest LPCTSTR
i jak LPCTSTR
(na przykład HDC
) i co oznacza?
LPCSTR p, q;
i chcesz const char *p, *q;
. Czy możesz odmówić ich użycia?
czym jest LPCTSTR
i jak LPCTSTR
(na przykład HDC
) i co oznacza?
LPCSTR p, q;
i chcesz const char *p, *q;
. Czy możesz odmówić ich użycia?
Odpowiedzi:
Cytując Briana Kramera na forach MSDN
LPCTSTR
= L ong P ointer do C onst T CHAR STR ing (Nie martw się, długi wskaźnik jest taki sam jak wskaźnik. Były dwa smaki wskaźników pod 16-bitowymi oknami.)Oto tabela:
LPSTR
=char*
LPCSTR
=const char*
LPWSTR
=wchar_t*
LPCWSTR
=const wchar_t*
LPTSTR
= wchar* or wchar_t*
zależności od_UNICODE
LPCTSTR
= wconst char* or const wchar_t*
zależności od_UNICODE
Nie trzeba nigdy używać żadnego z typów związanych z TCHAR.
Te typy, wszystkie typy struktur, które ich używają, i wszystkie powiązane funkcje są odwzorowywane w czasie kompilacji na wersję ANSI lub UNICODE (na podstawie konfiguracji projektu). Wersje ANSI zazwyczaj mają literę A dołączoną na końcu nazwy, a wersje Unicode dołączają literę W. Możesz użyć ich jawnie, jeśli wolisz. MSDN zanotuje to, gdy będzie to konieczne, na przykład wyświetla tutaj funkcję MessageBoxIndirectA i MessageBoxIndirectW: http://msdn.microsoft.com/en-us/library/windows/desktop/ms645511(v=vs.85).aspx
O ile nie atakujesz systemu Windows 9x, w którym brakuje implementacji wielu funkcji Unicode, nie ma potrzeby używania wersji ANSI. Jeśli celujesz w system Windows 9x, możesz użyć TCHAR do zbudowania pliku binarnego ansi i Unicode z tej samej bazy kodu, o ile twój kod nie zakłada, czy TCHAR jest char lub char.
Jeśli nie obchodzi Cię Windows 9x, zalecamy skonfigurowanie projektu jako Unicode i traktowanie TCHAR jako identycznego z WCHAR. Możesz jawnie korzystać z funkcji i typów W, jeśli wolisz, ale dopóki nie planujesz uruchomić projektu w systemie Windows 9x, nie ma to większego znaczenia.
Te typy są udokumentowane w Typach danych systemu Windows w witrynie MSDN:
LPCTSTR
LPCWSTR
JeśliUNICODE
jest zdefiniowana,LPCSTR
inaczej. Aby uzyskać więcej informacji, zobacz Typy danych systemu Windows dla ciągów.Ten typ jest zadeklarowany w WinNT.h w następujący sposób:
#ifdef UNICODE typedef LPCWSTR LPCTSTR; #else typedef LPCSTR LPCTSTR; #endif
LPCWSTR
Wskaźnik do stałego zakończonego znakiem null ciągu 16-bitowych znaków Unicode. Aby uzyskać więcej informacji, zobacz Zestawy znaków używane przez czcionki.
Ten typ jest zadeklarowany w WinNT.h w następujący sposób:
typedef CONST WCHAR *LPCWSTR;
HDC
Uchwyt kontekstu urządzenia (DC).
Ten typ jest zadeklarowany w WinDef.h w następujący sposób:
typedef HANDLE HDC;
Wiem, że to pytanie zostało zadane już jakiś czas temu i nie próbuję bezpośrednio odpowiedzieć na dokładnie oryginalne pytanie, ale ponieważ to konkretne pytanie ma przyzwoitą ocenę, chciałbym tu dodać trochę dla przyszłych czytelników. Ma to bardziej konkretny charakter Win32
API
typedefs
i sposób ich rozumienia.
Jeśli ktoś kiedykolwiek programował system Windows w czasach 32-bitowych maszyn od Windows 95 aż do Windows 7-8, rozumie i wie, że Win32
API
jest załadowany typedefs
i że większość jego funkcji i struktur, które mają zostać wypełnione i używane w dużej mierze na nich polegają.
Oto podstawowy program systemu Windows, który można przedstawić jako demonstrację.
#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;
}
To ledwo wystarczający kod do renderowania aplikacji Windows. Jest to najbardziej podstawowa konfiguracja zainicjować gołe minimalne właściwości czynią podstawową okno i jak widać jest już załadowany typedefs
z Win32
api
.
Rozbijmy to, patrząc na funkcje WinMain
i InitWindowsApp
: Pierwszą rzeczą są parametry funkcji HINSTANCE
i PSTR
:
WinMain
akceptuje pojedynczy HINSTANCE
obiekt, podczas gdy InitWindowsApp
akceptuje dwa HINSTANCE
obiekty obiekt PSTR lub inny typedef
ciąg znaków i int.
Użyję InitWindowsApp
tutaj funkcji, ponieważ da ona opis obiektu w obu funkcjach.
Pierwszy HINSTANCE
jest zdefiniowany jako H ile do INSTANCE, a ten jest najczęściej używany w aplikacji. Drugi jest drugim HANDLE
do poprzedniej INSTANCJI, która jest już rzadko używana. Został on zachowany dla starszych celów, aby nie musiał zmieniać WinMain()
podpisu funkcji, który zepsułby wiele już istniejących aplikacji w tym procesie. Trzecim parametrem jest P ointer do STR inż.
Musimy więc zapytać samych siebie, co to jest HANDLE
? Jeśli przyjrzymy się Win32
API
znajdującym się tutaj dokumentom: Typy danych systemu Windows , możemy łatwo to sprawdzić i sprawdzić, czy jest zdefiniowane jako:
Uchwyt do obiektu. Ten typ jest zadeklarowany w WinNT.h w następujący sposób:
typedef PVOID HANDLE;
Teraz mamy inny typedef
. Co jest PVOID
? To powinno być oczywiste, ale spójrzmy na to w tej samej tabeli ...
Wskaźnik do dowolnego typu. Jest to zadeklarowane w WinNT.h
typedef void *PVOID;
A HANDLE
służy do deklarowania wielu obiektów w Win32
API
takich rzeczach jak:
HKEY
- Uchwyt do klucza rejestru. Zadeklarowano w WinDef.h
typdef HANDLE HKEY;
HKL
- Uchwyt do identyfikatora lokalizacji. Zadeklarowano w WinDef.h
typdef HANDLE HKL;
HMENU
- Uchwyt do menu. Zadeklarowano w WinDef.h
typdef HANDLE HMENU;
HPEN
- Uchwyt do długopisu. Zadeklarowano w WinDef.h
typedef HANDLE HPEN;
HWND
- Uchwyt do okna. Zadeklarowano w WinDef.h
typedef HANDLE HWND;
HBRUSH
, HCURSOR
, HBITMAP
, HDC
, HDESK
, itd.Są to wszystkie typedefs
deklarowane za pomocą a, typedef
które jest a, HANDLE
a HANDLE
samo jest zadeklarowane jako typedef
od a, PVOID
które jest również a typedef
do a void pointer
.
Więc jeśli chodzi o LPCTSTR
to, możemy znaleźć to w tych samych dokumentach:
Jest zdefiniowany jako
LPCWSTR
ifUNICODE
lub wLPCSTR
inny sposób.
#ifdef UNICODE
typedef LPCWSTR LPCSTR;
#else
typedef LPCSTR LPCTSTR;
#endif
Mam więc nadzieję, że pomoże to w zrozumieniu sposobu użycia, typedefs
szczególnie w przypadku typów danych Windows, które można znaleźć w Win32
API
.
HANDLE
aliasy po aktywowaniu STRICT
makra. Myślę, że to domyślna opcja w nowych projektach.