what is LPCTSTR
and LPCTSTR
-like (for instance HDC
) and what it does stand for?

- 103
- 4
-
5Have you seen this: http://msdn.microsoft.com/en-us/library/aa300569%28v=vs.60%29.aspx ? – FrustratedWithFormsDesigner Apr 12 '13 at 17:03
-
3This is why we just love Microsoft. – zxcdw Apr 12 '13 at 18:22
-
2Those "types" always exhibit surprises, e.g. when you do `LPCSTR p, q;` and you wanted to have `const char *p, *q;`. Can you refuse to use them? – ott-- Apr 12 '13 at 20:38
-
9An abomination. – Thomas Eding Apr 16 '13 at 21:55
-
264 bit porting of a 32-bit application requires knowledge of such terminologies – overexchange Dec 02 '15 at 20:44
-
Related: [Windows Data Types](https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751.aspx) – CodesInChaos May 30 '17 at 08:49
4 Answers
Quoting Brian Kramer on the MSDN forums
LPCTSTR
= Long Pointer to a Const TCHAR STRing (Don't worry, a long pointer is the same as a pointer. There were two flavors of pointers under 16-bit windows.)Here's the table:
LPSTR
=char*
LPCSTR
=const char*
LPWSTR
=wchar_t*
LPCWSTR
=const wchar_t*
LPTSTR
=char* or wchar_t*
depending on_UNICODE
LPCTSTR
=const char* or const wchar_t*
depending on_UNICODE
-
30Every time I see that type name I feel like cringing. There's just something about it that makes me uncomfortable. (+1 BTW) – Donal Fellows Apr 13 '13 at 08:44
-
2
-
1@FlorianMargaine When an API tells you to. Just use the 'proper' types until then – James Apr 13 '13 at 13:43
-
"There were two flavors of pointers under 16-bit windows": Does the name come from back then? Some compilers used to call them far pointers... – Giorgio Dec 02 '15 at 20:02
-
1be warned, there are lots of caveats to be aware of here. wchar_t is a 16 bit type, but can be used to store both ucs2 and utf-16 encoded unicode characters. utf-16 may use multiple wchar_t's to encode a single letter, ucs2 only supports a subset of the unicode characterset. Which API functions you need to call also depend on the encoding used. – Michael Shaw Dec 03 '15 at 13:34
-
2The worst is DWORD, which used to be a 32 bit double word, but nowadays is a 32 bit half word :-) – gnasher729 Mar 05 '19 at 08:52
-
-
`TCHAR` (and thus `xxTSTR`) depends on `UNICODE`, not `_UNICODE`. Those are usually defined to be the same, but one is from `tchar.h` and one is from `windows.h`. Also, the wide typedef for it is to `WCHAR`, which is `unsigned short`, not `wchar_t`. Under the C++ standard, those are different types, even though VC++ treats them the same depending on some compiler switches. – Sebastian Redl Mar 05 '19 at 09:38
There's no need to ever use any of the types relating to TCHAR.
Those types, all structure types that use them, and all related functions are mapped at compile time to an ANSI or UNICODE version (based on your project's configuration). ANSI versions typically have an A appended to the end of the name, and unicode versions append a W. You can use these explicitly if you prefer. MSDN will note this when necessary, for example it lists a MessageBoxIndirectA and MessageBoxIndirectW function here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms645511(v=vs.85).aspx
Unless you are targeting Windows 9x, which lacked implementations of many unicode functions, there's no need to use the ANSI versions. If you are targeting Windows 9x, you can use TCHAR to build an ansi and unicode binary from the same codebase, as long as your code makes no assumptions about whether TCHAR is a char or wchar.
If you don't care about Windows 9x, I recommend configuring your project as unicode and treating TCHAR as identical to WCHAR. You can explicitly use the W functions and types if you prefer, but as long as you don't plan to run your project on Windows 9x, it doesn't really matter.

- 481
- 3
- 3
These types are documented at Windows Data Types on MSDN:
LPCTSTR
An
LPCWSTR
ifUNICODE
is defined, anLPCSTR
otherwise. For more information, see Windows Data Types for Strings.This type is declared in WinNT.h as follows:
#ifdef UNICODE typedef LPCWSTR LPCTSTR; #else typedef LPCSTR LPCTSTR; #endif
LPCWSTR
A pointer to a constant null-terminated string of 16-bit Unicode characters. For more information, see Character Sets Used By Fonts.
This type is declared in WinNT.h as follows:
typedef CONST WCHAR *LPCWSTR;
HDC
A handle to a device context (DC).
This type is declared in WinDef.h as follows:
typedef HANDLE HDC;

- 5,697
- 4
- 19
- 26
I know that this question was asked quite some time ago and I'm not trying to directly answer the exact original question, but as this particular Q/A has a decent rating I'd like to add a bit here for future readers. This has to do more specifically with the Win32
API
typedefs
and how to understand them.
If anyone has ever done any Windows programming during the era of the 32bit machines from Windows 95 through and up to Windows 7-8 they understand and know that the Win32
API
is loaded with typedefs
and that a majority of their functions and structures that are to be filled and used rely heavily on them.
Here is a basic windows program to give as a demonstration.
#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;
}
This is barely enough code to render a windows application. This is the most basic setup to initialize the bare minimal properties to render a basic window and as you can see it is already loaded with typedefs
from the Win32
api
.
Let's break it down by looking at the WinMain
and InitWindowsApp
functions: The first thing are the functions' parameters HINSTANCE
and PSTR
:
WinMain
accepts a single HINSTANCE
object while InitWindowsApp
accepts two HINSTANCE
objects a PSTR object or some other typedef
string and an int.
I'll use the InitWindowsApp
function here since it will give a description of the object in both functions.
The first HINSTANCE
is defined as a Handle to an INSTANCE and this is the one that is most commonly used for the application. The second one is another HANDLE
to a Previous INSTANCE which is rarely used anymore. It was kept around for legacy purpose in order to not have to change the WinMain()
function signature that would break many already existing applications in the process. The third parameter is a Pointer to a STRing.
So we have to ask our selves what is a HANDLE
? If we look in the Win32
API
docs found here:Windows Data Types we can easily look it up and see that it is defined as:
A handle to an object. This type is declared in WinNT.h as follows:
typedef PVOID HANDLE;
Now we have another typedef
. What is a PVOID
? Well it should be obvious but lets look that up in the same table...
A pointer to any type. This is declared in WinNT.h
typedef void *PVOID;
A HANDLE
is used to declare many objects in the Win32
API
things such as:
HKEY
- A handle to a registry key. Declared in WinDef.htypdef HANDLE HKEY;
HKL
- A handle to a locale identifier. Declared in WinDef.htypdef HANDLE HKL;
HMENU
- A handle to a menu. Declared in WinDef.htypdef HANDLE HMENU;
HPEN
- A handle to a pen. Declared in WinDef.htypedef HANDLE HPEN;
HWND
- A handle to a window. Declared in WinDef.htypedef HANDLE HWND;
- ... and so on such as
HBRUSH
,HCURSOR
,HBITMAP
,HDC
,HDESK
, etc.
These are all typedefs
that are declared using a typedef
which is a HANDLE
and the HANDLE
itself is declared as a typedef
from a PVOID
which is also a typedef
to a void pointer
.
So when it comes to LPCTSTR
we can find that in the same docs:
It is defined as a
LPCWSTR
ifUNICODE
is defined or aLPCSTR
otherwise.
#ifdef UNICODE
typedef LPCWSTR LPCSTR;
#else
typedef LPCSTR LPCTSTR;
#endif
So hopefully this will help as a guide as to how to understand the uses of typedefs
especially with the Windows Data Types that can be found in the Win32
API
.

- 127
- 8
-
Many of the handle types are more strongly typed than just being `HANDLE` aliases if you activate the `STRICT` macro. Which is the default in new projects, I think. – Sebastian Redl Mar 05 '19 at 11:01
-
@SebastianRedl It could be; but I wasn't trying to go into too much depth of the API and the strictness of the strongly typed aspects of the language. It was more of an overview of the Win32 API and its Data Types by the use of typedefs... – Francis Cugler Mar 05 '19 at 12:51