o que é LPCTSTR
e LPCTSTR
como (por exemplo HDC
) e o que representa?
LPCSTR p, q;
e queria ter const char *p, *q;
. Você pode se recusar a usá-los?
o que é LPCTSTR
e LPCTSTR
como (por exemplo HDC
) e o que representa?
LPCSTR p, q;
e queria ter const char *p, *q;
. Você pode se recusar a usá-los?
Respostas:
Citando Brian Kramer nos fóruns do MSDN
LPCTSTR
= L ong P ointer a um C onst T CHAR STR ing (não se preocupa, um ponteiro longo é o mesmo que um ponteiro. Houve dois sabores de ponteiros sob janelas de 16 bits).Aqui está a tabela:
LPSTR
=char*
LPCSTR
=const char*
LPWSTR
=wchar_t*
LPCWSTR
=const wchar_t*
LPTSTR
=char* or wchar_t*
dependendo de_UNICODE
LPCTSTR
=const char* or const wchar_t*
dependendo de_UNICODE
Não é necessário usar nenhum dos tipos relacionados ao TCHAR.
Esses tipos, todos os tipos de estrutura que os utilizam e todas as funções relacionadas são mapeadas em tempo de compilação para uma versão ANSI ou UNICODE (com base na configuração do seu projeto). As versões ANSI normalmente têm um A anexado ao final do nome e as versões unicode anexam um W. Você pode usá-las explicitamente, se preferir. O MSDN observará isso quando necessário, por exemplo, lista uma função MessageBoxIndirectA e MessageBoxIndirectW aqui: http://msdn.microsoft.com/en-us/library/windows/desktop/ms645511(v=vs.85).aspx
A menos que você esteja direcionando o Windows 9x, que carecia de implementações de muitas funções unicode, não há necessidade de usar as versões ANSI. Se você estiver direcionando o Windows 9x, poderá usar o TCHAR para criar um binário ansi e unicode a partir da mesma base de código, desde que o seu código não faça suposições sobre se o TCHAR é um caractere ou um wchar.
Se você não se importa com o Windows 9x, recomendo configurar seu projeto como unicode e tratar o TCHAR como idêntico ao WCHAR. Você pode usar explicitamente as funções e os tipos W, se preferir, mas desde que não planeje executar seu projeto no Windows 9x, isso realmente não importa.
Esses tipos estão documentados em Tipos de dados do Windows no MSDN:
LPCTSTR
Um
LPCWSTR
ifUNICODE
é definido, umLPCSTR
caso contrário. Para obter mais informações, consulte Tipos de dados do Windows para seqüências de caracteresEste tipo é declarado no WinNT.h da seguinte maneira:
#ifdef UNICODE typedef LPCWSTR LPCTSTR; #else typedef LPCSTR LPCTSTR; #endif
LPCWSTR
Um ponteiro para uma cadeia constante terminada por nulo constante de caracteres Unicode de 16 bits. Para mais informações, consulte Conjuntos de caracteres usados por fontes.
Este tipo é declarado no WinNT.h da seguinte maneira:
typedef CONST WCHAR *LPCWSTR;
HDC
Um identificador para um contexto de dispositivo (DC).
Este tipo é declarado no WinDef.h da seguinte maneira:
typedef HANDLE HDC;
Sei que essa pergunta foi feita há algum tempo e não estou tentando responder diretamente à pergunta original exata, mas como essa pergunta / pergunta específica tem uma classificação decente, gostaria de adicionar um pouco aqui para futuros leitores. Isso tem a ver mais especificamente com o Win32
API
typedefs
e como entendê-los.
Se alguém já fez alguma programação do Windows durante a era das máquinas de 32 bits, do Windows 95 até o Windows 7-8, ele entende e sabe que ele Win32
API
está carregado typedefs
e que a maioria de suas funções e estruturas devem ser preenchidas e usado dependem fortemente deles.
Aqui está um programa básico do Windows para dar como demonstração.
#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;
}
Este é apenas um código suficiente para renderizar um aplicativo do Windows. Essa é a configuração mais básica para inicializar as propriedades mínimas vazias para renderizar uma janela básica e, como você pode ver, ela já está carregada typedefs
no Win32
api
.
Vamos analisar detalhadamente as funções WinMain
e InitWindowsApp
: a primeira coisa são os parâmetros das funções HINSTANCE
e PSTR
:
WinMain
aceita um único HINSTANCE
objeto enquanto InitWindowsApp
aceita dois HINSTANCE
objetos, um objeto PSTR ou alguma outra typedef
string e um int.
Usarei a InitWindowsApp
função aqui, pois ela fornecerá uma descrição do objeto nas duas funções.
O primeiro HINSTANCE
é definido como um H andle para um INSTANCE e esse é o mais usado para o aplicativo. O segundo é outro HANDLE
de uma Instância Anterior que raramente é mais usada. Foi mantido para fins legados para não precisar alterar a WinMain()
assinatura da função que quebraria muitos aplicativos já existentes no processo. O terceiro parâmetro é um P ointer para uma STR ing.
Então temos que perguntar a nós mesmos o que é um HANDLE
? Se procurarmos nos Win32
API
documentos encontrados aqui: Tipos de dados do Windows , podemos consultá-lo facilmente e ver se ele está definido como:
Um identificador para um objeto. Este tipo é declarado no WinNT.h da seguinte maneira:
typedef PVOID HANDLE;
Agora temos outro typedef
. O que é um PVOID
? Bem, deve ser óbvio, mas vamos procurar isso na mesma tabela ...
Um ponteiro para qualquer tipo. Isso é declarado no WinNT.h
typedef void *PVOID;
A HANDLE
é usado para declarar muitos objetos Win32
API
, como:
HKEY
- Um identificador para uma chave do registro. Declarado em WinDef.h
typdef HANDLE HKEY;
HKL
- Um identificador para um identificador de localidade. Declarado em WinDef.h
typdef HANDLE HKL;
HMENU
- Uma alça para um menu. Declarado em WinDef.h
typdef HANDLE HMENU;
HPEN
- Uma alça para uma caneta. Declarado em WinDef.h
typedef HANDLE HPEN;
HWND
- Uma alça para uma janela. Declarado em WinDef.h
typedef HANDLE HWND;
HBRUSH
, HCURSOR
, HBITMAP
, HDC
, HDESK
, etc.Estes são todos os typedefs
que são declarados usando a typedef
que é a HANDLE
e o HANDLE
próprio é declarado como a typedef
de a PVOID
que também é a typedef
para a void pointer
.
Então, quando se trata de LPCTSTR
, podemos encontrar isso nos mesmos documentos:
É definido como um
LPCWSTR
seUNICODE
está definido ou deLPCSTR
outra forma.
#ifdef UNICODE
typedef LPCWSTR LPCSTR;
#else
typedef LPCSTR LPCTSTR;
#endif
Espero que isso ajude como um guia sobre como entender os usos de typedefs
especialmente com os tipos de dados do Windows que podem ser encontrados no Win32
API
.
HANDLE
aliases se você ativar a STRICT
macro. Qual é o padrão em novos projetos, eu acho.