cái gì LPCTSTR
và LPCTSTR
giống như (ví dụ HDC
) và nó đại diện cho cái gì?
LPCSTR p, q;
và bạn muốn có const char *p, *q;
. Bạn có thể từ chối sử dụng chúng?
cái gì LPCTSTR
và LPCTSTR
giống như (ví dụ HDC
) và nó đại diện cho cái gì?
LPCSTR p, q;
và bạn muốn có const char *p, *q;
. Bạn có thể từ chối sử dụng chúng?
Câu trả lời:
Trích dẫn Brian Kramer trên các diễn đàn MSDN
LPCTSTR
= L ong P con trỏ tới C onst T CHAR STR ing (Đừng lo lắng, một con trỏ dài giống như một con trỏ. Có hai hương vị của con trỏ dưới các cửa sổ 16 bit.)Đây là bảng:
LPSTR
= =char*
LPCSTR
= =const char*
LPWSTR
= =wchar_t*
LPCWSTR
= =const wchar_t*
LPTSTR
=char* or wchar_t*
tùy thuộc vào_UNICODE
LPCTSTR
=const char* or const wchar_t*
tùy thuộc vào_UNICODE
Không cần phải sử dụng bất kỳ loại nào liên quan đến TCHAR.
Các loại đó, tất cả các loại cấu trúc sử dụng chúng và tất cả các chức năng liên quan được ánh xạ tại thời điểm biên dịch thành phiên bản ANSI hoặc UNICODE (dựa trên cấu hình dự án của bạn). Các phiên bản ANSI thường có chữ A được gắn vào cuối tên và các phiên bản unicode nối thêm W. Bạn có thể sử dụng chúng một cách rõ ràng nếu bạn thích. MSDN sẽ lưu ý điều này khi cần thiết, ví dụ, nó liệt kê một hàm MessageBoxInirectA và MessageBoxInirectW tại đây: http://msdn.microsoft.com/en-us/l Library / windows / desktop / ms645511 (v = vs85) .aspx
Trừ khi bạn đang nhắm mục tiêu Windows 9x, thiếu triển khai nhiều chức năng unicode, không cần sử dụng các phiên bản ANSI. Nếu bạn đang nhắm mục tiêu Windows 9x, bạn có thể sử dụng TCHAR để xây dựng nhị phân ansi và unicode từ cùng một cơ sở mã, miễn là mã của bạn không đưa ra giả định nào về việc TCHAR là char hay wchar.
Nếu bạn không quan tâm đến Windows 9x, tôi khuyên bạn nên định cấu hình dự án của mình là unicode và coi TCHAR giống hệt với WCHAR. Bạn có thể sử dụng rõ ràng các chức năng và loại W nếu bạn thích, nhưng miễn là bạn không có kế hoạch chạy dự án của mình trên Windows 9x, điều đó không thực sự quan trọng.
Các loại này được ghi lại tại Windows Data Type trên MSDN:
LPCTSTR
Một
LPCWSTR
nếuUNICODE
được định nghĩa, mộtLPCSTR
cách khác. Để biết thêm thông tin, hãy xem Kiểu dữ liệu Windows cho Chuỗi.Loại này được khai báo trong WinNT.h như sau:
#ifdef UNICODE typedef LPCWSTR LPCTSTR; #else typedef LPCSTR LPCTSTR; #endif
LPCWSTR
Một con trỏ tới một chuỗi ký tự Unicode 16 bit không có ký tự kết thúc. Để biết thêm thông tin, hãy xem Bộ ký tự được sử dụng bởi phông chữ.
Loại này được khai báo trong WinNT.h như sau:
typedef CONST WCHAR *LPCWSTR;
HDC
Một xử lý cho một bối cảnh thiết bị (DC).
Loại này được khai báo trong WinDef.h như sau:
typedef HANDLE HDC;
Tôi biết rằng câu hỏi này đã được hỏi cách đây khá lâu và tôi không cố gắng trả lời trực tiếp câu hỏi ban đầu chính xác, nhưng vì Q / A cụ thể này có một đánh giá khá tốt tôi muốn thêm một chút ở đây cho độc giả tương lai. Điều này phải làm cụ thể hơn với Win32
API
typedefs
và làm thế nào để hiểu chúng.
Nếu bất cứ ai đã từng thực hiện bất kỳ chương trình Windows nào trong kỷ nguyên của các máy 32 bit từ Windows 95 cho đến Windows 7-8, họ sẽ hiểu và biết rằng phần mềm Win32
API
này được tải typedefs
và phần lớn các chức năng và cấu trúc của chúng sẽ được lấp đầy và được sử dụng dựa nhiều vào chúng.
Đây là một chương trình windows cơ bản để trình diễn.
#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;
}
Đây chỉ là mã đủ để kết xuất một ứng dụng windows. Đây là thiết lập cơ bản nhất để khởi tạo các thuộc tính tối thiểu để hiển thị một cửa sổ cơ bản và như bạn có thể thấy nó đã được tải typedefs
từ Win32
api
.
Chúng ta hãy phá vỡ nó bằng cách xem xét các hàm WinMain
và InitWindowsApp
chức năng: Điều đầu tiên là các tham số của hàm HINSTANCE
và PSTR
:
WinMain
chấp nhận một HINSTANCE
đối tượng trong khi InitWindowsApp
chấp nhận hai HINSTANCE
đối tượng một đối tượng PSTR hoặc một số typedef
chuỗi khác và int.
Tôi sẽ sử dụng InitWindowsApp
hàm ở đây vì nó sẽ đưa ra mô tả về đối tượng trong cả hai hàm.
Cái đầu tiên HINSTANCE
được định nghĩa là H andle to INSTANCE và đây là cái được sử dụng phổ biến nhất cho ứng dụng. Cái thứ hai là cái khác HANDLE
với INSTANCE trước đây hiếm khi được sử dụng nữa. Nó được giữ xung quanh cho mục đích kế thừa để không phải thay đổi WinMain()
chữ ký hàm sẽ phá vỡ nhiều ứng dụng đã tồn tại trong quy trình. Tham số thứ ba là P ointer to STR ing.
Vì vậy, chúng ta phải hỏi bản thân của chúng ta là HANDLE
gì? Nếu chúng ta tìm trong các Win32
API
tài liệu tìm thấy ở đây: Các kiểu dữ liệu Windows, chúng ta có thể dễ dàng tra cứu và thấy rằng nó được định nghĩa là:
Một tay cầm cho một đối tượng. Loại này được khai báo trong WinNT.h như sau:
typedef PVOID HANDLE;
Bây giờ chúng tôi có một cái khác typedef
. Là PVOID
gì Chà điều đó là hiển nhiên nhưng hãy tìm kiếm điều đó trong cùng một bảng ...
Một con trỏ đến bất kỳ loại. Điều này được khai báo trong WinNT.h
typedef void *PVOID;
A HANDLE
được sử dụng để khai báo nhiều đối tượng trong những Win32
API
điều như:
HKEY
- Một tay cầm để đăng ký khóa. Được khai báo trong WinDef.h
typdef HANDLE HKEY;
HKL
- Một tay cầm để nhận dạng miền địa phương. Được khai báo trong WinDef.h
typdef HANDLE HKL;
HMENU
- Một tay cầm để một menu. Được khai báo trong WinDef.h
typdef HANDLE HMENU;
HPEN
- Một tay cầm bút. Được khai báo trong WinDef.h
typedef HANDLE HPEN;
HWND
- Một tay cầm để một cửa sổ. Được khai báo trong WinDef.h
typedef HANDLE HWND;
HBRUSH
, HCURSOR
, HBITMAP
, HDC
, HDESK
,, vvĐây là tất cả những typedefs
gì được khai báo sử dụng a typedef
là a HANDLE
và HANDLE
chính nó được khai báo là a typedef
từ a PVOID
cũng là typedef
a void pointer
.
Vì vậy, khi nói đến LPCTSTR
chúng ta có thể tìm thấy điều đó trong cùng một tài liệu:
Nó được định nghĩa là
LPCWSTR
nếuUNICODE
được định nghĩa hoặcLPCSTR
khác.
#ifdef UNICODE
typedef LPCWSTR LPCSTR;
#else
typedef LPCSTR LPCTSTR;
#endif
Vì vậy, hy vọng điều này sẽ giúp ích như một hướng dẫn về cách hiểu cách sử dụng typedefs
đặc biệt với các Kiểu dữ liệu Windows có thể tìm thấy trong Win32
API
.
HANDLE
bí danh nếu bạn kích hoạt STRICT
macro. Đó là mặc định trong các dự án mới, tôi nghĩ.