czym jest LPCTSTRi 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 LPCTSTRi 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_UNICODELPCTSTR= 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
LPCWSTRJeśliUNICODEjest zdefiniowana,LPCSTRinaczej. 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
LPCWSTRWskaź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;
HDCUchwyt 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 typedefsi 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 APIjest załadowany typedefsi ż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 typedefsz Win32 api.
Rozbijmy to, patrząc na funkcje WinMaini InitWindowsApp: Pierwszą rzeczą są parametry funkcji HINSTANCEi PSTR:
WinMainakceptuje pojedynczy HINSTANCEobiekt, podczas gdy InitWindowsAppakceptuje dwa HINSTANCEobiekty obiekt PSTR lub inny typedefciąg znaków i int.
Użyję InitWindowsApptutaj funkcji, ponieważ da ona opis obiektu w obu funkcjach.
Pierwszy HINSTANCEjest zdefiniowany jako H ile do INSTANCE, a ten jest najczęściej używany w aplikacji. Drugi jest drugim HANDLEdo 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 APIznajdują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 HANDLEsłuży do deklarowania wielu obiektów w Win32 APItakich 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 typedefsdeklarowane za pomocą a, typedefktóre jest a, HANDLEa HANDLEsamo jest zadeklarowane jako typedefod a, PVOIDktóre jest również a typedefdo a void pointer.
Więc jeśli chodzi o LPCTSTRto, możemy znaleźć to w tych samych dokumentach:
Jest zdefiniowany jako
LPCWSTRifUNICODElub wLPCSTRinny 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, typedefsszczególnie w przypadku typów danych Windows, które można znaleźć w Win32 API.
HANDLEaliasy po aktywowaniu STRICTmakra. Myślę, że to domyślna opcja w nowych projektach.