|
| |
| Version 0.1 ▪ Draft | ||
WinAPI functions often appear in two reincarnations, ANSI and Unicode.
Let’s look at MessageBox.
In fact, it does not really exist as a function.
Instead, it is a #define'd identifier, which is mapped to one of two real functions,
MessageBoxA or MessageBoxW.
In WinUser.h:
#ifdef UNICODE
#define MessageBox MessageBoxW
#else
#define MessageBox MessageBoxA
#endif // !UNICODE
The difference between functions is in types of string parameters,
ANSI in MessageBoxA and Unicode in MessageBoxW:
int MessageBoxA(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
int MessageBoxW(HWND hWnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType);
One could call “real” functions directly, though usually it is not supposed to be done:
MessageBoxA(NULL, "Text", "Caption", MB_OK);
MessageBoxW(NULL, L"Text", L"Caption", MB_OK);
What is expected should be rather
MessageBox(NULL, TEXT("Text"), TEXT("Caption"), MB_OK);
When UNICODE is defined, the TEXT macro adds "L" to the strings.
It is also possible to use _T instead of TEXT so save a couple of characters and perhaps to improve readability.
There were two string types so far, LPCSTR and LPCWSTR.
However, in analogy with all this ANSI/Unicode story, common practice is to use agnostic LPCTSTR.
It is a typedef, either for LPCSTR or for LPCWSTR,
depending, as easy to guess, on UNICODE define.
The following is more or less canonical form of the code.
LPCTSTR lpszText = _T("Text");
LPCTSTR lpszCaption = _T("Caption");
MessageBox(NULL, lpszText, lpszCaption, MB_OK);
LPCTSTR and LPTSTR
It is easy. "C" is for const.
After getting through hierarchy of typedefs, one could figure out something like the following:
LPSTR ≡ char *
LPCSTR ≡ const char *
LPWSTR ≡ wchar_t *
LPCWSTR ≡ const wchar_t *
TCHAR
Similarly to strings, TCHAR is typedef'ed either to char or to wchar_t.
TCHAR*, PTSTR, PCTSTR and alikeWell, WinAPI does not have strong consistency. This is not a big surprise, taking into account long history and backward compatibility issues.
For instance, "P" and "LP" were to distinguish between normal pointers and long pointers years ago.
As far as my experience shows, most consistent way is to use LPCTSTR and LPTSTR.
More information about windows types can be found e.g. here.
BTW, similarly to two versions of WinAPI, there are alternative versions of runtime functions. Here the picture is even a bit more complex, because besides ANSI and Unicode, multi-byte character set is coming to the game.
For instance, depending on defining of _UNICODE and _MBCS,
_tcschr (search for a character in a string)
can be mapped to strchr, to _mbschr, or to wcschr.
Pay attention that this time _UNICODE has the leading underscore.
It controls C runtime headers, while UNICODE controls Windows headers.
See this post.
Sometimes there is a need to be explicit. Functions MultiByteToWideChar and WideCharToMultiByte do conversion in WinAPI way.