що таке LPCTSTR
і LPCTSTR
-подібне (наприклад HDC
) і що воно означає?
LPCSTR p, q;
хотіли і хотіли const char *p, *q;
. Чи можете ви відмовитися від їх використання?
що таке LPCTSTR
і LPCTSTR
-подібне (наприклад HDC
) і що воно означає?
LPCSTR p, q;
хотіли і хотіли const char *p, *q;
. Чи можете ви відмовитися від їх використання?
Відповіді:
Цитуючи Брайана Крамера на форумах 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
Ніколи не потрібно використовувати жоден із типів, що стосуються 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, у якій бракувало реалізації багатьох функцій unicode, не потрібно використовувати версії ANSI. Якщо ви орієнтовані на Windows 9x, ви можете використовувати TCHAR для створення бінарних файлів ansi та unicode з тієї самої бази коду, якщо ваш код не передбачає припущень щодо того, чи є TCHAR char чи wchar.
Якщо ви не переймаєтесь Windows 9x, рекомендую налаштувати ваш проект як unicode і розглянути TCHAR як ідентичний WCHAR. Якщо ви хочете, ви можете явно використовувати функції та типи W, але поки ви не плануєте запускати проект у Windows 9x, це насправді не має значення.
Ці типи задокументовано у типах даних Windows на MSDN:
LPCTSTR
LPCWSTR
, ЯкщоUNICODE
визначено, вLPCSTR
іншому випадку. Для отримання додаткової інформації див. Типи даних Windows для рядків.Цей тип оголошено в WinNT.h наступним чином:
#ifdef UNICODE typedef LPCWSTR LPCTSTR; #else typedef LPCSTR LPCTSTR; #endif
LPCWSTR
Вказівник на постійний рядок з нульовим завершенням 16-бітних символів Unicode. Для отримання додаткової інформації див. Набори символів, використовувані шрифтами.
Цей тип оголошено в WinNT.h наступним чином:
typedef CONST WCHAR *LPCWSTR;
HDC
Ручка до контексту пристрою (DC).
Цей тип оголошено в WinDef.h наступним чином:
typedef HANDLE HDC;
Я знаю, що це запитання було задано досить давно, і я не намагаюся безпосередньо відповісти на точне оригінальне запитання, але оскільки цей конкретний Q / A має гідну оцінку, я хотів би трохи додати тут для майбутніх читачів. Це стосується конкретніших питань 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 до ИНСТАНЦИИ , і це той , який найбільш часто використовується для додатка. Друга - це ще 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
ми можемо знайти це в тих же документах:
Він визначається як a,
LPCWSTR
якщоUNICODE
визначено, абоLPCSTR
іншим чином.
#ifdef UNICODE
typedef LPCWSTR LPCSTR;
#else
typedef LPCSTR LPCTSTR;
#endif
Отож, сподіваємось, це допоможе в якості посібника щодо того, як зрозуміти використання typedefs
особливо з типами даних Windows, які можна знайти в Win32
API
.
HANDLE
псевдоніми, якщо активувати STRICT
макрос. Я думаю, що за замовчуванням у нових проектах.