Was ist LPCTSTR?


37

Was ist LPCTSTRund LPCTSTRwie (zum Beispiel HDC) und wofür steht es?



3
Deshalb lieben wir Microsoft einfach.
zxcdw

2
Diese "Typen" zeigen immer Überraschungen, z. B. wenn Sie sie haben LPCSTR p, q;und haben wollen const char *p, *q;. Können Sie sich weigern, sie zu benutzen?
ott--

9
Ein Gräuel.
Thomas Eding

2
64 - Bit - Portierung einer 32-Bit - Anwendung erfordert die Kenntnis solcher Terminologien
overexchange

Antworten:


76

Zitiert Brian Kramer in den MSDN-Foren

LPCTSTR= L Ong P ointer zu einem C onst T CHAR STR ing (keine Sorge, ein langer Zeiger ist das gleiche wie ein Zeiger. Zwei Arten von Zeigern gibt unter 16-Bit - Fenstern waren.)

Hier ist die Tabelle:

  • LPSTR = char*
  • LPCSTR = const char*
  • LPWSTR = wchar_t*
  • LPCWSTR = const wchar_t*
  • LPTSTR= char* or wchar_t*abhängig von_UNICODE
  • LPCTSTR= const char* or const wchar_t*abhängig von_UNICODE

29
Jedes Mal, wenn ich diesen Typnamen sehe, habe ich das Gefühl, zusammenzucken. Es gibt nur etwas, das mich unwohl macht. (+1 BTW)
Donal Fellows

2
Wann sollte ich dann diese Art von Zeiger verwenden?
Florian Margaine

@FlorianMargaine Wenn Sie von einer API dazu aufgefordert werden. Verwenden Sie einfach die "richtigen" Typen bis dahin
James

1
seien sie gewarnt, hier gibt es viele vorbehalte zu beachten. wchar_t ist ein 16-Bit-Typ, der jedoch sowohl zum Speichern von UCS2- als auch von UTF-16-codierten Unicode-Zeichen verwendet werden kann. utf-16 kann mehrere wchar_t verwenden, um einen einzelnen Buchstaben zu kodieren. ucs2 unterstützt nur eine Teilmenge des Unicode-Zeichensatzes. Welche API-Funktionen Sie aufrufen müssen, hängt auch von der verwendeten Codierung ab.
Michael Shaw

2
Das Schlimmste ist DWORD, das früher ein 32-Bit-Doppelwort war, aber heute ist es ein 32-Bit-
Halbwort

6

Es ist nicht erforderlich, jemals einen der TCHAR-Typen zu verwenden.

Diese Typen, alle Strukturtypen, die sie verwenden, und alle zugehörigen Funktionen werden zur Kompilierungszeit einer ANSI- oder UNICODE-Version zugeordnet (basierend auf der Konfiguration Ihres Projekts). ANSI-Versionen haben normalerweise ein A am Ende des Namens und Unicode-Versionen ein W. Sie können diese explizit verwenden, wenn Sie dies vorziehen. MSDN merkt sich dies bei Bedarf. Beispielsweise werden hier die Funktionen MessageBoxIndirectA und MessageBoxIndirectW aufgelistet: http://msdn.microsoft.com/en-us/library/windows/desktop/ms645511(v=vs.85).aspx

Sofern Sie nicht auf Windows 9x abzielen, für das viele Unicode-Funktionen nicht implementiert waren, müssen Sie die ANSI-Versionen nicht verwenden. Wenn Sie auf Windows 9x abzielen, können Sie mit TCHAR eine Ansi- und Unicode-Binärdatei aus derselben Codebasis erstellen, sofern in Ihrem Code keine Annahmen darüber getroffen werden, ob es sich bei TCHAR um ein Zeichen oder ein Zeichen handelt.

Wenn Sie sich nicht für Windows 9x interessieren, empfehle ich, Ihr Projekt als Unicode zu konfigurieren und TCHAR als mit WCHAR identisch zu behandeln. Sie können die W-Funktionen und -Typen nach Belieben explizit verwenden, aber solange Sie nicht vorhaben, Ihr Projekt unter Windows 9x auszuführen, spielt es keine Rolle.


0

Diese Typen sind unter Windows-Datentypen in MSDN dokumentiert :

LPCTSTR

Ein LPCWSTRWenn UNICODEist definiert, ein LPCSTRAnderes. Weitere Informationen finden Sie unter Windows-Datentypen für Zeichenfolgen.

Dieser Typ wird in WinNT.h wie folgt deklariert:

#ifdef UNICODE
 typedef LPCWSTR LPCTSTR; 
#else
 typedef LPCSTR LPCTSTR;
#endif

LPCWSTR

Ein Zeiger auf eine konstante nullterminierte Zeichenfolge mit 16-Bit-Unicode-Zeichen. Weitere Informationen finden Sie unter Von Schriftarten verwendete Zeichensätze.

Dieser Typ wird in WinNT.h wie folgt deklariert:

typedef CONST WCHAR *LPCWSTR;

HDC

Ein Handle zu einem Gerätekontext (DC).

Dieser Typ wird in WinDef.h wie folgt deklariert:

typedef HANDLE HDC;

0

Ich weiß, dass diese Frage vor einiger Zeit gestellt wurde und ich versuche nicht, die genaue ursprüngliche Frage direkt zu beantworten, aber da diese Frage eine anständige Bewertung hat, möchte ich hier ein wenig für zukünftige Leser hinzufügen. Dies hat insbesondere mit dem zu tun Win32 API typedefsund wie man sie versteht.

Wenn jemand im Zeitalter der 32-Bit-Computer von Windows 95 bis Windows 7-8 jemals Windows-Programmierungen durchgeführt hat, versteht er und weiß, dass die Win32 APImit typedefsund mit einem Großteil seiner Funktionen und Strukturen gefüllt werden müssen verwendet verlassen sich stark auf sie.


Hier ist ein grundlegendes Windows-Programm zur Demonstration.

#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;
}

Dies ist kaum genug Code, um eine Windows-Anwendung zu rendern. Dies ist die Grundeinstellung der nackten minimalen Eigenschaften zu initialisieren ein Grundfenster zu machen und wie Sie es bereits geladen mit sehen können typedefsaus dem Win32 api.


Lassen Sie es uns zusammenfassen, indem wir uns die WinMainund InitWindowsApp-Funktionen ansehen: Das Erste sind die Parameter der Funktionen HINSTANCEund PSTR:

WinMainakzeptiert ein einzelnes HINSTANCEObjekt, während InitWindowsAppzwei HINSTANCEObjekte ein PSTR-Objekt oder eine andere typedefZeichenfolge und ein Int.

Ich werde die InitWindowsAppFunktion hier verwenden, da sie eine Beschreibung des Objekts in beiden Funktionen enthält.

Das erste HINSTANCEist als ein H- andle zu einer INSTANZ definiert und dies ist dasjenige, das am häufigsten für die Anwendung verwendet wird. Der zweite ist ein anderer HANDLEzu einem früheren INSTANZ, der selten mehr verwendet wird. Es wurde zu Legacy-Zwecken aufbewahrt, um die WinMain()Funktionssignatur nicht ändern zu müssen, die viele bereits vorhandene Anwendungen im Prozess beschädigen würde. Der dritte Parameter ist ein P ointer zu einem STR ing.

Also müssen wir uns selbst fragen, was ist ein HANDLE? In den folgenden Win32 APIDokumenten finden Sie Informationen zu Windows-Datentypen :

Ein Handle zu einem Objekt. Dieser Typ wird in WinNT.h wie folgt deklariert:

typedef PVOID HANDLE; 

Jetzt haben wir noch einen typedef. Was ist ein PVOID? Nun, es sollte offensichtlich sein, aber lassen Sie uns das in der gleichen Tabelle nachschlagen ...

Ein Zeiger auf einen beliebigen Typ. Dies ist in WinNT.h deklariert

typedef void *PVOID;

A HANDLEwird verwendet, um viele Objekte in den folgenden Win32 APIDingen zu deklarieren :

  • HKEY - Ein Handle für einen Registrierungsschlüssel. In WinDef.h deklariert
    • typdef HANDLE HKEY;
  • HKL - Ein Handle zu einer Gebietsschemabezeichnung. In WinDef.h deklariert
    • typdef HANDLE HKL;
  • HMENU - Ein Griff zu einem Menü. In WinDef.h deklariert
    • typdef HANDLE HMENU;
  • HPEN - Ein Griff zu einem Stift. In WinDef.h deklariert
    • typedef HANDLE HPEN;
  • HWND - Ein Griff an ein Fenster. In WinDef.h deklariert
    • typedef HANDLE HWND;
  • ... und so weiter, wie HBRUSH, HCURSOR, HBITMAP, HDC, HDESK, usw.

Dies sind alles typedefs, typedefwas mit a, das a ist, deklariert wird, HANDLEund das HANDLEselbst wird als typedefvon a, PVOIDdas auch a ist, typedefzu a deklariert void pointer.


Wenn es also darum geht, LPCTSTRkönnen wir das in den gleichen Dokumenten finden:

Es ist definiert als LPCWSTRob UNICODEdefiniert ist oder LPCSTRnicht.

#ifdef UNICODE
  typedef LPCWSTR LPCSTR;
#else
  typedef LPCSTR LPCTSTR;
#endif

So hoffentlich wird dies als Leitfaden helfen , wie die Verwendungen zu verstehen , typedefsvor allem mit den Windows - Datentypen , die in der zu finden sind Win32 API.


Viele der Handle-Typen sind stärker typisiert als nur HANDLEAliase, wenn Sie das STRICTMakro aktivieren . Welches ist der Standard in neuen Projekten, denke ich.
Sebastian Redl

@SebastianRedl Es könnte sein; Aber ich habe nicht versucht, zu viel über die API und die Strenge der stark typisierten Aspekte der Sprache zu erfahren. Es war eher eine Übersicht über die Win32-API und ihre Datentypen durch die Verwendung von typedefs ...
Francis Cugler
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.