Что такое LPCTSTR?


37

что LPCTSTRи LPCTSTRкак (например HDC) и что это означает?



3
Вот почему мы просто любим Microsoft.
zxcdw

2
Эти «типы» всегда показывают сюрпризы, например, когда вы делаете, LPCSTR p, q;и вы хотели иметь const char *p, *q;. Можете ли вы отказаться от их использования?
ott--

9
Мерзость
Томас Эдинг

2
64-битное портирование 32-битного приложения требует знания такой терминологии
overexchange

Ответы:


76

Цитировать Брайана Крамера на форумах MSDN

LPCTSTR= L Ong P ointer к C onst T CHAR STR Инг (не волнуйтесь, длинный указатель такой же , как указатель. Были две разновидности указателей под 16-битных Windows.)

Вот таблица:

  • LPSTR знак равно char*
  • LPCSTR знак равно const char*
  • LPWSTR знак равно wchar_t*
  • LPCWSTR знак равно const wchar_t*
  • LPTSTR= в char* or wchar_t*зависимости от_UNICODE
  • LPCTSTR= в const char* or const wchar_t*зависимости от_UNICODE

29
Каждый раз, когда я вижу это имя типа, мне хочется съежиться. В этом есть что-то, что заставляет меня чувствовать себя неловко. (+1 Кстати)
Донал Феллоуз

2
Когда я должен использовать указатель такого типа?
Флориан Маргэйн

@FlorianMargaine Когда API говорит вам. Просто используйте «правильные» типы до тех пор
Джеймс

1
будьте осторожны, здесь есть много предостережений, о которых нужно знать. wchar_t - это 16-битный тип, но его можно использовать для хранения кодированных в кодировке ucs2 и utf-16 символов Юникода. utf-16 может использовать несколько символов wchar_t для кодирования одной буквы, ucs2 поддерживает только подмножество набора символов Unicode. Какие функции API вам нужно вызвать, также зависит от используемой кодировки.
Майкл Шоу

2
Наихудшим является DWORD, который раньше был 32-битным двойным словом, но сейчас это 32-битное полуслово :-)
gnasher729

6

Нет необходимости использовать какие-либо типы, относящиеся к TCHAR.

Эти типы, все типы структур, которые их используют, и все связанные функции отображаются во время компиляции в версию ANSI или UNICODE (в зависимости от конфигурации вашего проекта). В версиях ANSI обычно к концу имени добавляется буква A, а в версиях Unicode добавляется буква W. Вы можете использовать их явно, если хотите. MSDN заметит это при необходимости, например, перечисляет функции MessageBoxIndirectA и MessageBoxIndirectW здесь: http://msdn.microsoft.com/en-us/library/windows/desktop/ms645511(v=vs.85).aspx

Если вы не нацелены на Windows 9x, в которой отсутствовали реализации многих функций Юникода, нет необходимости использовать версии ANSI. Если вы ориентируетесь на Windows 9x, вы можете использовать TCHAR для создания бинарных файлов ANSI и Unicode из одной и той же кодовой базы, если ваш код не делает предположений о том, является ли TCHAR символом или wchar.

Если вас не волнует Windows 9x, я рекомендую настроить ваш проект как Unicode и рассматривать TCHAR как идентичный WCHAR. Вы можете явно использовать функции и типы W, если хотите, но если вы не планируете запускать свой проект в Windows 9x, это не имеет значения.


0

Эти типы описаны в разделе Типы данных Windows на MSDN:

LPCTSTR

LPCWSTR, Если UNICODEопределено, в LPCSTRпротивном случае. Для получения дополнительной информации см. Типы данных Windows для строк.

Этот тип объявлен в WinNT.h следующим образом:

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

LPCWSTR

Указатель на постоянную строку с нулевым символом в конце, состоящую из 16-битных символов Юникода. Для получения дополнительной информации см. Наборы символов, используемые шрифтами.

Этот тип объявлен в WinNT.h следующим образом:

typedef CONST WCHAR *LPCWSTR;

HDC

Дескриптор контекста устройства (DC).

Этот тип объявлен в WinDef.h следующим образом:

typedef HANDLE HDC;

0

Я знаю, что этот вопрос задавался довольно давно, и я не пытаюсь прямо ответить на точный оригинальный вопрос, но, поскольку этот конкретный вопрос / ответ имеет достойную оценку, я хотел бы добавить сюда немного для будущих читателей. Это связано с тем, Win32 API typedefsкак и как их понимать.

Если кто-то когда-либо занимался программированием для Windows в эпоху 32-битных машин от Windows 95 до Windows 7-8 и выше, они понимают и знают, что они Win32 APIзагружены typedefsи что большинство их функций и структур должны быть заполнены и использовать в большой степени полагаться на них.


Вот базовая программа для Windows, которую можно продемонстрировать в качестве демонстрации.

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

Этого едва хватает для рендеринга приложения Windows. Это самая базовая настройка для инициализации минимальных минимальных свойств для рендеринга основного окна, и, как вы можете видеть, оно уже загружено typedefsиз Win32 api.


Давайте разорвать его, глядя на WinMainи InitWindowsAppфункции: Первое , это параметры функций HINSTANCEи PSTR:

WinMainпринимает один HINSTANCEобъект, в то время как InitWindowsAppпринимает два HINSTANCEобъекта: объект PSTR или некоторую другую typedefстроку и int.

Я буду использовать InitWindowsAppфункцию здесь, так как она даст описание объекта в обеих функциях.

Первый HINSTANCEопределяется как H andle для INSTANCE, и именно этот наиболее часто используется для приложения. Второй - это другой HANDLEпредыдущий инстанс, который редко используется больше. Он хранился в унаследованных целях, чтобы не приходилось изменять WinMain()сигнатуру функции, которая может нарушить работу многих уже существующих приложений. Третий параметр является Р ointer к STR Инж.

Итак, мы должны спросить себя, что это HANDLE? Если мы посмотрим на Win32 APIдокументы, найденные здесь: Типы данных Windows, мы можем легко найти их и увидеть, что они определены как:

Дескриптор объекта. Этот тип объявлен в WinNT.h следующим образом:

typedef PVOID HANDLE; 

Теперь у нас есть другой typedef. Что это PVOID? Ну, это должно быть очевидно, но давайте посмотрим на это в той же таблице ...

Указатель на любой тип. Это объявлено в WinNT.h

typedef void *PVOID;

A HANDLEиспользуется для объявления многих объектов в Win32 APIтаких вещах, как:

  • HKEY - Дескриптор ключа реестра. Объявлен в WinDef.h
    • typdef HANDLE HKEY;
  • HKL - Дескриптор идентификатора локали. Объявлен в WinDef.h
    • typdef HANDLE HKL;
  • HMENU - Ручка к меню. Объявлен в WinDef.h
    • typdef HANDLE HMENU;
  • HPEN - Ручка к ручке. Объявлен в WinDef.h
    • typedef HANDLE HPEN;
  • HWND - Ручка к окну. Объявлен в WinDef.h
    • typedef HANDLE HWND;
  • ... и так далее , такие как HBRUSH, HCURSOR, HBITMAP, HDC, HDESKи т.д.

Это все typedefs, которые объявлены с использованием a, typedefкоторый является a, HANDLEа HANDLEсам по себе объявлен как a typedefиз a, PVOIDкоторый также является a typedefдля a void pointer.


Поэтому, когда дело доходит до LPCTSTRнас, мы можем найти это в тех же документах:

Это определяется как LPCWSTRесли UNICODEопределено или LPCSTRиначе.

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

Надеюсь, это поможет вам понять, как использовать typedefsособенности типов данных Windows, которые можно найти в Win32 API.


Многие из типов дескрипторов более строго типизированы, чем просто HANDLEпсевдонимы, если вы активируете STRICTмакрос. Что по умолчанию в новых проектах, я думаю.
Себастьян Редл

@SebastianRedl Это может быть; но я не пытался углубиться в API и строгость строго типизированных аспектов языка. Это был скорее обзор Win32 API и его типов данных с использованием typedefs ...
Фрэнсис Куглер
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.