що таке 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*залежно від_UNICODELPCTSTR=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макрос. Я думаю, що за замовчуванням у нових проектах.