MFC+OSG(Open Secene Graph)場(chǎng)景實(shí)現(xiàn)中文HUD(head up display)效果,防止中文亂碼
背景:為什么同時(shí)使用MFC和OSG
我建立了一個(gè)MFC工程,以O(shè)SG作為視圖顯示的基礎(chǔ),通過(guò)點(diǎn)擊MFC菜單啟動(dòng)某些功能。因此,在工程中包含了OSG庫(kù)。并且,為了使生成的exe在Windows下能正常處理中文路徑,使用**多字節(jié)字符集(ANSI)**作為編碼方式。因此,程序中并不會(huì)使用L()
宏來(lái)定義Unicode字符串,也不會(huì)使用wchar等寬字符類(lèi)型,而是所有字符串都用一樣的寫(xiě)法,比如:
const char* pHUDText="我愛(ài)你中國(guó)";
如果不考慮OSG,這種寫(xiě)法完全沒(méi)有問(wèn)題,運(yùn)行MFC程序、使用MFC對(duì)話框顯示和讀取中文輸入都是正常工作的。
但是,我的工程中還引入了OSG庫(kù),這個(gè)庫(kù)僅支持utf-8的字符串顯示。所以我必須將要輸入OSG顯示的中文字符串轉(zhuǎn)換成utf-8編碼格式。為了完成這件事,進(jìn)行了下面幾種嘗試:
-
MSVC項(xiàng)目屬性中加入 /execution-charset:utf-8
操作如下圖所示:
代碼中仍使用正常的字符串寫(xiě)法。 -
使用u8字符串
-
使用函數(shù)將字符串轉(zhuǎn)到utf-8編碼(使用支持C++11的編譯器時(shí),完全可以由方法2替代)。定義如下:
#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);
}
其中CP_ACP就是指當(dāng)前代碼頁(yè)。CP_UTF8指的是65001(utf-8)代碼頁(yè)。gb2312toUTF8
的第一個(gè)參數(shù)是傳入的待轉(zhuǎn)換字符串,第二個(gè)參數(shù)是結(jié)果字符串。
詳解三種使字符串能在OSG中顯示的方法
/execution-charset:utf-8 設(shè)置程序執(zhí)行時(shí)的編碼為utf-8
即程序源碼中的字符串編譯后在可執(zhí)行程序或庫(kù)中的編碼方式都由此選項(xiàng)控制。如果一個(gè)MSVC項(xiàng)目在命令行加入了這一項(xiàng),則程序中的所有字符串都會(huì)按照utf-8編碼存儲(chǔ)。
u8字符串字面量
使用u8字符串字面量?jī)H對(duì)當(dāng)前字符串的編碼指定為utf-8存儲(chǔ)。即,如果程序本身是按系統(tǒng)的ANSI編碼正常工作,設(shè)置u8字符串字面量
示例:
#include <iostream>
int main()
{
std::cout << u8"大家好";
}
在這段代碼中,編譯器會(huì)將"大家好"三個(gè)漢字按照utf-8編碼存進(jìn)生成的.exe程序中。執(zhí)行程序時(shí),按照Windows系統(tǒng)默認(rèn)代碼頁(yè)(ANSI,936)從.exe中讀取這段字符數(shù)據(jù),并輸出到命令行。這當(dāng)然會(huì)亂碼啦!如圖所示:
但是,如果你打開(kāi)命令行后,將命令行的代碼頁(yè)切換到utf-8,再運(yùn)行這個(gè)程序,則會(huì)輸出正確的結(jié)果。如下圖所示:
GB2312toUTF8函數(shù)
通過(guò)WINAPI將字符串從默認(rèn)代碼頁(yè)ANSI轉(zhuǎn)到Unicode,再?gòu)腢nicode轉(zhuǎn)到utf-8。
總結(jié)
像我的應(yīng)用場(chǎng)景,MFC+OSG場(chǎng)景顯示,MFC程序中的字符讀取都還是按ANSI編碼,僅僅將輸入OSG的字符串轉(zhuǎn)換為utf-8編碼,所以不適合采用第一種策略(將所有字符串都以u(píng)tf-8編碼存儲(chǔ))。第二種方法和第三種方法是等價(jià)的,且在編譯器支持u8字符串字面量時(shí)更推薦第二種方法,簡(jiǎn)潔又省事。
如果已經(jīng)在C/C+±命令行中加入了/execution-charset:utf-8,但是在程序中又同時(shí)使用了GB2312toUTF8函數(shù)將字符串轉(zhuǎn)換,則又會(huì)導(dǎo)致亂碼。例如:
int main()
{
std::string str, str1, str2;
str1 = "大家好!\n";
str2 = u8"大家好!\n";
gb2312ToUtf8(str1, str);
std::cout << str;
std::cout << str1;
std::cout << str2;
}
在65001代碼頁(yè)中的運(yùn)行結(jié)果為:文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-720089.html
可見(jiàn),這三種方式只使用其中一種即可,u8和/execution-charset:utf-8
不沖突,而gb2312ToUtf8
和/execution-charset:utf-8
同時(shí)使用是不行的。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-720089.html
到了這里,關(guān)于MFC+OSG(Open Secene Graph)場(chǎng)景實(shí)現(xiàn)中文HUD(head up display)效果,防止中文亂碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!