I believe modern Windows Win32/C++ applications should just use Unicode builds, instead of the obsolete TCHAR model.
For example, consider some Win32/C++ code like this:
CString str; TCHAR* buf = str.GetBuffer(maxLength); // Write something in buf ... buf[n] = L'\0'; // (1) str.ReleaseBuffer(); // Other code ... TCHAR * text = /* some valid output buffer */; swprintf_s(text, L"Something ...", ...); // (2) // DoSomething() is declared as: // // void DoSomething(const wchar_t* psz); // DoSomething(text); // (3)
The author of that piece of code thinks he followed the TCHAR model, probably because he used TCHAR throughout his code; but he’s wrong. For example:
- If buf is a TCHAR*, the correct TCHAR-model assignment should be “buf[n] = _T(‘\0’);”, i.e. use the _T or TEXT preprocessor macros instead of the L prefix.
- swprintf_s should be substituted with _stprintf_s, and again the L prefix should be substituted with the _T or TEXT preprocessor macros.
- The TCHAR string “text” should be converted to a wchar_t string before passing it to the DoSomething function, e.g. using an ATL helper like CT2W or CT2CW (e.g. “DoSomething(CT2W(text));”).
So, following the TCHAR model would actually make the code more complicated. And for what?
For being able to compile the same source code also in ANSI/MBCS? And is the whole code base properly tested for ANSI/MBCS builds? And in case of ANSI/MBCS builds, what code page(s) is(are) used for char-based strings? Are the conversions from those code pages to Unicode done properly? This can be a bug factory! And, do you (or your clients) really need an ANSI/MBCS build of your software??
So, in my opinion, the best thing to do in modern Win32 C++ applications is to just forget about the TCHAR model, and to just use Unicode UTF-16 at least at the Win32 API boundary, and just use WCHAR or wchar_t instead of TCHAR (in other words: assume that TCHAR is wchar_t), and assume that Win32 APIs that take TCHAR-strings (e.g. SetWindowText) just take Unicode UTF-16 wchar_t-strings.
In other words: Just assume Unicode builds for Win32 C++ code.
I’d rewrite the above code fragment simply assuming that TCHAR is wchar_t, like this:
CString str; // CString stores Unicode UTF-16 text // in Unicode builds wchar_t* buf = str.GetBuffer(maxLength); // Write something in buf ... buf[n] = L'\0'; str.ReleaseBuffer(); // Other code ... wchar_t * text = /* some valid output buffer */; swprintf_s(text, L"Something ...", ...); // DoSomething() is declared as: // // void DoSomething(const wchar_t* psz); // DoSomething(text);
It’s also interesting to point out that some “modern” (e.g. Vista+) Windows APIs like DrawThemeTextEx just take Unicode (UTF-16) strings; i.e. the pszText parameter of the aforementioned API is of type LPCWSTR, i.e. “const WCHAR*” (instead of LPCTSTR, i.e. “const TCHAR*”).
One Reply to “A Friendly Piece of Advice: The TCHAR Model? Forget About It!”