fix Win32/Win64 garbled "Chinese" window titles in UNICODE builds. Fix #27645 #27646
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Pull Request Readiness Checklist
See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request
[ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicablePatch to opencv_extra has the same branch name.
and sample code can be built with the project CMakefix Win32/Win64 garbled "Chinese" window titles in UNICODE builds. See also see also https://stackoverflow.com/questions/33358546/chinese-characters-in-title-bar for an equivalent problem. This fix does away with all the usual ANSI API hacks as that DOES NOT fly as soon as you have a user-defined Windows message handler callback, which calls DefWindowProc et al.
This fix introduces a generic approach which works for all ANSI and UNICODE builds, where an assistant class is presented to do the heavy lifting back & forth between UTF8/
char*
/CHAR
and UCS2/UTF16/WCHAR
for anyone who needs it. The design intent is for this class to be used as a temporary instance, presenting a pointer to its internal storage for the duration of an API call, where & when needed.The supplied
T()
macro is merely a small service to make the code more readable. (Old MFC hacks will gnash their dentures, I'm sure :-) )The rest of the implementation uses the default Win32 API calls as offered by Microsoft system header files (no A or W suffix), plus the advised
TEXT()
macro to ensure any string constant is properly tagged for the compiler to produce the correct content and type (char/wchar_t -> LPCSTR/LPCWSTR).NEVER use CHAR/LPSTR/LPCSTR/... for ANSI/UNICODE build portable code; use TCHAR/LPTSTR/LPCTSTR/... instead and have your support code ready to deal with TCHAR being either
char
or UCS2/UTF16wchar_t
. This is a corollary of Microsoft's advice to not mix ANSI and UNICODE API calls in the same run-time (that's EXE + DLLs all). You may get away with an ANSI patch (I often do!) when you're not using UI/GUI API calls, but once you need those (as OpenCV does here to open a window pane to show an image), the game is up. A sensible rule-of-thumb test is: does your Win32 API usage possibly involve a Windows Message Loop under the hood? --> if not answerable by an empathetic NO, then refrain from using any ANSI calls.This also fixes a very minor issue about a very cute
while(0)
hack that doesn't fly as soon as you compile with the warning level dialed up beyond vanilla W3 (we build this stuff with ALL warnings turned on -- the MSVC simile of-Wpedantic
: see the code comment there.From the code:
Win32UIClass: assistant class to ease compiling this in both classic ANSI mode and modern UNICODE builds.
the moral of the story for this entire source file: ditch the Win32 A (ANSI) API calls' hack, and use what they (MS) hand you as-is (W or A, depending on your compile settings) and transform any strings to the type that's needed: ANSI/UTF8 or UCS2/UTF16.
root cause: see also https://stackoverflow.com/questions/33358546/chinese-characters-in-title-bar which was someone else with what turned out to be the same exhibit (this code also has DefWindowProc calls in the window handlers making the whole thing b0rk if you're not extra-special careful in coding this sort of thing.
Bottom line: as soon as you're using DefWindowProc in any way, stick with what Microsoft
system header files give you as the 'default' Win32 API and deal! TCHAR, TEXT(), etc.
Re:
do ... while (0);
:while(0,0) instead of while(0) to avoid MSVC compiler warning C4127: "conditional expression is constant" ... but now gives us this instead:
warning C4548 : expression before comma has no effect; expected expression with side-effect
--> no way around using
#pragma warning(disable)
then.