Co oznacza LPCWSTR i jak należy sobie z tym radzić?

91

Po pierwsze, co to dokładnie jest? Wydaje mi się, że jest to wskaźnik (LPC oznacza stałą długiego wskaźnika), ale co oznacza „W”? Czy jest to określony wskaźnik do ciągu, czy wskaźnik do określonego ciągu? Na przykład chcę zamknąć okno o nazwie „TestWindow”.

HWND g_hTest;
LPCWSTR a;
*a = ("TestWindow");
g_hTest = FindWindowEx(NULL, NULL, NULL, a);
DestroyWindow(g_hTest);

Kod jest nielegalny i nie działa, ponieważ const char [6] nie może zostać przekonwertowane na CONST WCHAR. W ogóle tego nie rozumiem. Chcę uzyskać dokładne zrozumienie wszystkich tych LPCWSTR, LPCSTR, LPSTR. Próbowałem coś znaleźć, ale jeszcze bardziej się pogubiłem. W witrynie msdn FindWindowExjest zadeklarowana jako

HWND FindWindowEx(      
    HWND hwndParent,
    HWND hwndChildAfter,
    LPCTSTR lpszClass,
    LPCTSTR lpszWindow
);

Zatem ostatnim parametrem jest LPCSTR, a kompilator wymaga LPCWSTR. Proszę pomóż.

lhj7362
źródło
59
Witamy w notacji węgierskiej firmy Microsoft.
Thomas Matthews
2
w rzeczywistości sprawia, że ​​dokumentacja jest znacznie bardziej czytelna, szkoda wszystkiego innego na ten temat sux.
Matt Joiner,
1
@ Thomas: To nie jest to, co początkowo Microsoft (lub Simonyi) oznaczył notacją węgierską . Jest to mniej więcej skutek wypadku, kiedy grupa dokumentacji zdecydowała się na pewne ulepszenia „czytelności”. Nie byli programistami, więc zmiany nie były wdzięczne. Podstawowe informacje są dostępne w notacji hugariańskiej - teraz moja kolej :)
Niespodziewane
@IInspectable: Zepsuty link
Nicolas Raoul
1
@IInspectable: Link roboczy to blogs.msdn.microsoft.com/larryosterman/2004/06/22/…
Julius Bullinger

Odpowiedzi:

137

LPCWSTRoznacza „Long Pointer to Constant Wide String”. W oznacza Wide i oznacza, że ​​łańcuch jest przechowywany w postaci 2-bajtowej w porównaniu z normalnym char. Wspólne dla każdego kodu C / C ++, który ma do czynienia tylko z ciągami znaków spoza ASCII. =

Aby otrzymać zwykły ciąg literału C do przypisania do a LPCWSTR, musisz poprzedzić go literą L

LPCWSTR a = L"TestWindow";
JaredPar
źródło
8
Wystarczy rozszerzyć - część „LONG” to kac po 16-bitowych oknach i można ją zignorować (z wyjątkiem tego, że jest to potrzebne w nazwie)
Martin Beckett
14
„kac z 16-bitowego systemu Windows” - to na pewno!
John Dibling,
4
Nie, to prawda. To był i jest 32-bitowy wskaźnik. Nie ma już „krótkich” 16-bitowych wskaźników, więc możesz narzekać, jeśli uda Ci się znaleźć plik SPCWSTR.
MSalters
50
Mój Boże. L ??? Litera L? Nawet funkcja, L ()? Po prostu zwykły L? Kto do cholery na to wpadł?
john ktejik
12
@ user396483 W wielu językach często dodaje się przedrostki i sufiksy do stałych, aby zmienić sposób ich przedstawiania, bez zmiany ich znaczenia dla człowieka. Na przykład 36ULw C # to to samo, co (ulong)36(ulong to 64-bitowa liczba całkowita bez znaku). @mogą być używane w tym samym języku, co prefiks dla łańcuchów, zmieniając nieznacznie sposób ich przetwarzania.
Zenexer,
12

LPCWSTRjest równoważne wchar_t const *. Jest to wskaźnik do szerokiego ciągu znaków, który nie zostanie zmodyfikowany przez wywołanie funkcji.

Możesz przypisać do LPCWSTRs, dołączając L do literału ciągu:LPCWSTR *myStr = L"Hello World";

LPC T STR i wszystkie inne typy T , weź typ ciągu w zależności od ustawień Unicode dla twojego projektu. Jeśli _UNICODEzdefiniowano dla twojego projektu, użycie typów T jest takie samo jak szerokich formularzy znaków, w przeciwnym razie formularzy Ansi. Odpowiednia funkcja będzie również nazywana w ten sposób: FindWindowExjest definiowana jako FindWindowExAlub w FindWindowExWzależności od tej definicji.

Matt Joiner
źródło
7

Jest to długi wskaźnik do stałego, szerokiego ciągu (tj. Ciągu szerokich znaków).

Ponieważ jest to szeroki łańcuch, chcesz, aby stałej wyglądać następująco: L"TestWindow". Nie tworzyłbym też pośredniego a, po prostu podałbym L"TestWindow"parametr:

ghTest = FindWindowEx(NULL, NULL, NULL, L"TestWindow");

Jeśli chcesz być pedantycznie poprawny, „LPCTSTR” jest ciągiem tekstowym - szerokim ciągiem w kompilacji Unicode i wąskim ciągiem w kompilacji ANSI, więc powinieneś użyć odpowiedniego makra:

ghTest = FindWindow(NULL, NULL, NULL, _T("TestWindow"));

Niewiele osób interesuje się tworzeniem kodu, który można skompilować zarówno dla zestawów znaków Unicode, jak i ANSI, a jeśli nie sprawisz, że będzie działał poprawnie, może to wymagać trochę dodatkowej pracy przy niewielkim zysku. W tym konkretnym przypadku nie ma wiele dodatkowej pracy, ale jeśli manipulujesz ciągami znaków, istnieje cały zestaw makr do manipulacji na ciągach, które są rozwiązywane na prawidłowe funkcje.

Jerry Coffin
źródło
1
nie musisz być pedantycznie poprawny, użyj _T () jeśli używasz stałych, takich jak _T (MAIN_WINDOW), w przeciwnym razie LMAIN_WINDOW zawiedzie.
Rodolfo