o que é LPCTSTRe LPCTSTRcomo (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 é LPCTSTRe LPCTSTRcomo (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_UNICODELPCTSTR=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:
LPCTSTRUm
LPCWSTRifUNICODEé definido, umLPCSTRcaso 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
LPCWSTRUm 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;
HDCUm 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 typedefse 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 APIestá carregado typedefse 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 typedefsno Win32 api.
Vamos analisar detalhadamente as funções WinMaine InitWindowsApp: a primeira coisa são os parâmetros das funções HINSTANCEe PSTR:
WinMainaceita um único HINSTANCEobjeto enquanto InitWindowsAppaceita dois HINSTANCEobjetos, um objeto PSTR ou alguma outra typedefstring e um int.
Usarei a InitWindowsAppfunçã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 HANDLEde 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 APIdocumentos 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 typedefsque são declarados usando a typedefque é a HANDLEe o HANDLEpróprio é declarado como a typedefde a PVOIDque também é a typedefpara a void pointer.
Então, quando se trata de LPCTSTR, podemos encontrar isso nos mesmos documentos:
É definido como um
LPCWSTRseUNICODEestá definido ou deLPCSTRoutra forma.
#ifdef UNICODE
typedef LPCWSTR LPCSTR;
#else
typedef LPCSTR LPCTSTR;
#endif
Espero que isso ajude como um guia sobre como entender os usos de typedefsespecialmente com os tipos de dados do Windows que podem ser encontrados no Win32 API.
HANDLEaliases se você ativar a STRICTmacro. Qual é o padrão em novos projetos, eu acho.