Apa itu LPCTSTR?


37

apa itu LPCTSTRdan LPCTSTR-seperti (misalnya HDC) dan apa artinya?



3
Inilah sebabnya kami sangat menyukai Microsoft.
zxcdw

2
"Jenis" tersebut selalu menunjukkan kejutan, misalnya ketika Anda melakukannya LPCSTR p, q;dan Anda ingin memilikinya const char *p, *q;. Bisakah Anda menolak menggunakannya?
ott--

9
Kekejian.
Thomas Eding

2
Porting 64 bit dari aplikasi 32-bit membutuhkan pengetahuan tentang terminologi seperti itu
overexchange

Jawaban:


76

Mengutip Brian Kramer di forum MSDN

LPCTSTR= L ong P ointer ke C onst T CHAR STR ing (Jangan khawatir, pointer panjang adalah sama dengan pointer. Ada dua rasa dari pointer di bawah 16-bit jendela.)

Ini tabelnya:

  • LPSTR = char*
  • LPCSTR = const char*
  • LPWSTR = wchar_t*
  • LPCWSTR = const wchar_t*
  • LPTSTR= char* or wchar_t*tergantung pada_UNICODE
  • LPCTSTR= const char* or const wchar_t*tergantung pada_UNICODE

29
Setiap kali saya melihat nama tipe itu saya merasa ingin ngeri. Ada sesuatu tentang hal itu yang membuat saya tidak nyaman. (+1 BTW)
Donal Fellows

2
Kapan saya harus menggunakan pointer semacam ini?
Florian Margaine

@FlorianMargaine Saat API memberitahu Anda. Cukup gunakan tipe yang 'tepat' sampai saat itu
James

1
diperingatkan, ada banyak peringatan yang harus diperhatikan di sini. wchar_t adalah tipe 16 bit, tetapi dapat digunakan untuk menyimpan karakter unicode yang disandikan ucs2 dan utf-16. utf-16 dapat menggunakan multiple wchar_t untuk mengkodekan satu huruf, ucs2 hanya mendukung subset dari rangkaian kode unicode. Fungsi API mana yang perlu Anda panggil juga bergantung pada penyandian yang digunakan.
Michael Shaw

2
Yang terburuk adalah DWORD, yang dulunya merupakan kata ganda 32 bit, tetapi saat ini adalah kata setengah 32 bit :-)
gnasher729

6

Tidak perlu menggunakan jenis apa pun yang berhubungan dengan TCHAR.

Tipe-tipe itu, semua tipe struktur yang menggunakannya, dan semua fungsi terkait dipetakan pada waktu kompilasi ke versi ANSI atau UNICODE (berdasarkan pada konfigurasi proyek Anda). Versi ANSI biasanya memiliki A yang ditambahkan ke akhir nama, dan versi unicode menambahkan W. Anda dapat menggunakan ini secara eksplisit jika Anda mau. MSDN akan mencatat ini bila perlu, misalnya ia mencantumkan fungsi MessageBoxIndirectA dan MessageBoxIndirectW di sini: http://msdn.microsoft.com/en-us/library/windows/desktop/ms645511(v=vs.85).aspx

Kecuali jika Anda menargetkan Windows 9x, yang tidak memiliki implementasi banyak fungsi unicode, tidak perlu menggunakan versi ANSI. Jika Anda menargetkan Windows 9x, Anda dapat menggunakan TCHAR untuk membangun ansi dan unicode biner dari basis kode yang sama, selama kode Anda tidak membuat asumsi tentang apakah TCHAR adalah char atau wchar.

Jika Anda tidak peduli dengan Windows 9x, saya sarankan mengkonfigurasi proyek Anda sebagai unicode dan memperlakukan TCHAR sebagai identik dengan WCHAR. Anda dapat secara eksplisit menggunakan fungsi dan tipe W jika Anda mau, tetapi selama Anda tidak berencana untuk menjalankan proyek Anda pada Windows 9x, itu tidak terlalu penting.


0

Tipe-tipe ini didokumentasikan pada Tipe Data Windows di MSDN:

LPCTSTR

Sebuah LPCWSTRjika UNICODEdidefinisikan, sebuah LPCSTRsebaliknya. Untuk informasi lebih lanjut, lihat Tipe Data Windows untuk String.

Jenis ini dideklarasikan di WinNT.h sebagai berikut:

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

LPCWSTR

Pointer ke string null-dihentikan konstan karakter Unicode 16-bit. Untuk informasi lebih lanjut, lihat Kumpulan Karakter yang Digunakan Oleh Font.

Jenis ini dideklarasikan di WinNT.h sebagai berikut:

typedef CONST WCHAR *LPCWSTR;

HDC

Pegangan ke konteks perangkat (DC).

Jenis ini dideklarasikan di WinDef.h sebagai berikut:

typedef HANDLE HDC;

0

Saya tahu bahwa pertanyaan ini ditanyakan beberapa waktu yang lalu dan saya tidak mencoba untuk langsung menjawab pertanyaan asli yang sebenarnya, tetapi karena Tanya Jawab khusus ini memiliki peringkat yang layak, saya ingin menambahkan sedikit di sini untuk pembaca masa depan. Ini harus dilakukan lebih khusus dengan Win32 API typedefsdan bagaimana memahaminya.

Jika ada yang pernah melakukan pemrograman Windows selama era mesin 32-bit dari Windows 95 hingga Windows 7-8, mereka mengerti dan tahu bahwa Win32 APIitu dimuat dengan typedefsdan bahwa sebagian besar fungsi dan struktur mereka yang harus diisi dan digunakan sangat bergantung pada mereka.


Berikut ini adalah program windows dasar untuk diberikan sebagai demonstrasi.

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

Ini hampir tidak cukup kode untuk membuat aplikasi windows. Ini adalah pengaturan paling dasar untuk menginisialisasi properti minimal telanjang untuk membuat jendela dasar dan seperti yang Anda lihat itu sudah diambil typedefsdari Win32 api.


Mari kita memecahnya dengan melihat WinMaindan InitWindowsAppfungsi: Hal pertama adalah parameter fungsi HINSTANCEdan PSTR:

WinMainmenerima satu HINSTANCEobjek sementara InitWindowsAppmenerima dua HINSTANCEobjek objek PSTR atau typedefstring lain dan int.

Saya akan menggunakan InitWindowsAppfungsi di sini karena akan memberikan deskripsi objek di kedua fungsi.

Yang pertama HINSTANCEdidefinisikan sebagai H andle ke INSTANCE dan ini adalah yang paling umum digunakan untuk aplikasi. Yang kedua adalah yang lain HANDLEdari INSTANCE Sebelumnya yang jarang digunakan lagi. Itu disimpan di sekitar untuk tujuan warisan agar tidak harus mengubah WinMain()tanda tangan fungsi yang akan merusak banyak aplikasi yang sudah ada dalam proses. Parameter ketiga adalah P ointer ke STR .

Jadi kita harus bertanya pada diri kita sendiri apa itu HANDLE? Jika kita melihat pada Win32 APIdokumen yang ditemukan di sini: Tipe Data Windows kita dapat dengan mudah mencarinya dan melihat bahwa itu didefinisikan sebagai:

Pegangan ke objek. Jenis ini dideklarasikan di WinNT.h sebagai berikut:

typedef PVOID HANDLE; 

Sekarang kita punya yang lain typedef. Apa itu PVOID? Yah itu harus jelas tetapi mari kita lihat di tabel yang sama ...

Pointer untuk jenis apa pun. Ini dinyatakan dalam WinNT.h

typedef void *PVOID;

A HANDLEdigunakan untuk mendeklarasikan banyak objek dalam Win32 APIhal-hal seperti:

  • HKEY - Pegangan ke kunci registri. Dinyatakan dalam WinDef.h
    • typdef HANDLE HKEY;
  • HKL - Pegangan ke pengenal lokal. Dinyatakan dalam WinDef.h
    • typdef HANDLE HKL;
  • HMENU - Pegangan ke menu. Dinyatakan dalam WinDef.h
    • typdef HANDLE HMENU;
  • HPEN - Gagang untuk pena. Dinyatakan dalam WinDef.h
    • typedef HANDLE HPEN;
  • HWND - Pegangan ke jendela. Dinyatakan dalam WinDef.h
    • typedef HANDLE HWND;
  • ... dan seterusnya seperti HBRUSH, HCURSOR, HBITMAP, HDC, HDESK, dll

Ini semua typedefsyang dideklarasikan menggunakan a typedefyang merupakan HANDLEdan HANDLEitu sendiri dinyatakan sebagai typedefdari PVOIDyang juga typedefke a void pointer.


Jadi ketika sampai pada LPCTSTRkita dapat menemukannya di dokumen yang sama:

Ini didefinisikan sebagai LPCWSTRjika UNICODEdidefinisikan atau LPCSTRsebaliknya.

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

Jadi semoga ini akan membantu sebagai panduan bagaimana memahami penggunaan typedefsterutama dengan Jenis Data Windows yang dapat ditemukan di Internet Win32 API.


Banyak tipe pegangan yang diketik lebih kuat daripada hanya menjadi HANDLEalias jika Anda mengaktifkan STRICTmakro. Yang merupakan default dalam proyek baru, saya pikir.
Sebastian Redl

@SebastianRedl Bisa jadi; tapi saya tidak mencoba masuk ke kedalaman API dan ketelitian aspek bahasa yang diketik dengan sangat ketat. Itu lebih merupakan gambaran umum dari Win32 API dan Tipe Data dengan menggunakan typedefs ...
Francis Cugler
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.