MFC+OSG (Open Secene Graph) scene implements Chinese HUD (head up display) effect to prevent Chinese garbled characters

MFC+OSG (Open Secene Graph) scene implements Chinese HUD (head up display) effect to prevent Chinese garbled characters

Background: Why use both MFC and OSG

I created an MFC project, using OSG as the basis for view display, and started certain functions by clicking on the MFC menu. Therefore, the OSG library is included in the project. Moreover, in order to enable the generated exe to process Chinese paths normally under Windows, use **Multibyte Character Set (ANSI)** as the encoding method. Therefore, the program does not use the L() macro to define Unicode strings, nor does it use wchar equal-width character types. Instead, all strings are written in the same way, such as:

const char* pHUDText="我爱你中国";

If OSG is not considered, there is no problem with this writing method. Running MFC programs, using MFC dialog boxes to display and reading Chinese input all work normally.
However, my project also introduced the OSG library, which only supports UTF-8 string display. So I have to convert the Chinese string to be input to OSG for display into utf-8 encoding format. In order to accomplish this, the following attempts were made:

  1. Add /execution-charset:utf-8 to the MSVC project properties
    The operation is as shown below:
    Insert image description here
    Normal strings are still used in the code Writing method.

  2. Use u8 string

  3. Use a function to convert the string to UTF-8 encoding (can be completely replaced by method 2 when using a compiler that supports C++11). The definition is as follows:

#include<Windows.h>//WideCharToMultiByte定义在这里
void unicodeToUTF8(const std::wstring &src, std::string& result) 
{
    
     
	int n = WideCharToMultiByte( CP_UTF8, 0, src.c_str(), -1, 0, 0, 0, 0 ); 
	result.resize(n); 
	::WideCharToMultiByte( CP_UTF8, 0, src.c_str(), -1, (char*)result.c_str(), result.length(), 0, 0 ); 
}

void gb2312ToUnicode(const std::string& src, std::wstring& result) 
{
    
     
	int n = MultiByteToWideChar( CP_ACP, 0, src.c_str(), -1, NULL, 0 ); 
	result.resize(n); 
	::MultiByteToWideChar( CP_ACP, 0, src.c_str(), -1, (LPWSTR)result.c_str(), result.length()); 
}

void gb2312toUTF8(const std::string& src, std::string& result) 
{
    
     
	std::wstring strWideChar; 
	gb2312ToUnicode(src, strWideChar); 
	unicodeToUTF8(strWideChar, result); 
}

where CP_ACP refers to the current code page. CP_UTF8 refers to the 65001 (utf-8) code page. The first parameter of
gb2312toUTF8 is the incoming string to be converted, and the second parameter is the result string.

Detailed explanation of three methods to enable strings to be displayed in OSG

/execution-charset:utf-8 sets the encoding when the program is executed to utf-8

That is, the encoding method of strings in the program source code in the executable program or library after compilation is controlled by this option. If an MSVC project adds this item to the command line, all strings in the program will be stored in UTF-8 encoding.

u8 string literal

Use u8 string literal to specify only the encoding of the current string to be stored as utf-8. That is, if the program itself works normally according to the system's ANSI encoding, set the u8 string literal
Example:

#include <iostream>

int main()
{
    
    
    std::cout << u8"大家好";
}

In this code, the compiler will store the three Chinese characters "Hello everyone" into the generated .exe program according to UTF-8 encoding. When executing the program, this character data is read from the .exe according to the Windows system default code page (ANSI, 936) and output to the command line. Of course this will be garbled! As shown in the figure:
u8 strings in 936 code page
However, if you open the command line, switch the code page of the command line to utf-8, and then run this program, the correct result will be output. As shown below:

u8 string in 65001 code page

GB2312toUTF8 function

Convert the string from the default code page ANSI to Unicode through WINAPI, and then from Unicode to utf-8.

Summarize

Like my application scenario, the MFC+OSG scenario shows that the characters read in the MFC program are still encoded in ANSI, and only the string input to OSG is converted to utf-8 encoding, so the first strategy (converting all the characters) is not suitable. Strings are stored in UTF-8 encoding). The second method and the third method are equivalent, and the second method is recommended when the compiler supports u8 string literals, which is concise and trouble-free.

If /execution-charset:utf-8 has been added to the C/C++ command line, but the GB2312toUTF8 function is also used to convert the string in the program, garbled characters will result. For example:

int main()
{
    
    
    std::string str, str1, str2;
    str1 = "大家好!\n";
    str2 = u8"大家好!\n";
    gb2312ToUtf8(str1, str);
    std::cout << str;
    std::cout << str1;
    std::cout << str2;
}

The running result in the 65001 code page is:

Insert image description here
It can be seen that only one of these three methods can be used. u8 and /execution-charset:utf-8 do not conflict, but gb2312ToUtf8 and /execution-charset:utf-8It is not possible to use them at the same time.

Guess you like

Origin blog.csdn.net/qq_42679415/article/details/133233761