UTF-8编码波兰语在MFC程序中显示异常问题咨询
我之前在做MFC多语言项目时,也踩过东欧语言(比如波兰语)显示异常的坑,结合你的描述,大概率是编码转换逻辑、字符集设置或者LANGID的误用导致的,给你几个实操性的解决方向:
MFC的AfxMessageBox和UI控件依赖的是TCHAR字符串(UNICODE项目里是UTF-16,ANSI项目里是系统默认ANSI),直接把UTF-8字节数组塞进去肯定乱码。正确的转换步骤应该是这样:
// 假设pUtf8Content是从语言文件读取到的UTF-8字节数据,nByteLen是字节长度 int wideCharLen = MultiByteToWideChar(CP_UTF8, 0, (LPCCH)pUtf8Content, nByteLen, NULL, 0); CString wideStr; if (wideCharLen > 0) { MultiByteToWideChar(CP_UTF8, 0, (LPCCH)pUtf8Content, nByteLen, wideStr.GetBuffer(wideCharLen), wideCharLen); wideStr.ReleaseBuffer(); // 现在用这个宽字符串去显示就正常了 AfxMessageBox(wideStr); }
另外读取文件时一定要用二进制模式,避免Windows自动对换行符或编码做手脚,比如用CFile的话要加CFile::typeBinary标记。
你代码里写的LANGID languageID = 65001是错误的!65001是UTF-8代码页的编号,而LANGID是语言标识(比如波兰语的LANGID是MAKELANGID(LANG_POLISH, SUBLANG_DEFAULT),对应数值0x0415)。如果要获取波兰语默认代码页,得传正确的LANGID:
LANGID plLangId = MAKELANGID(LANG_POLISH, SUBLANG_DEFAULT); TCHAR szCodepage[10]; GetLocaleInfo(plLangId, LOCALE_IDEFAULTCODEPAGE, szCodepage, _countof(szCodepage)); // 不过如果咱们已经用UTF-8文件了,其实直接用CP_UTF8转码就行,不用取默认代码页
强烈建议把你的MFC项目设置为使用Unicode字符集(项目属性→配置属性→常规→字符集)。ANSI模式下MFC对非西欧语言的支持非常有限,尤其是UTF-8转ANSI时很容易丢失特殊字符(比如波兰语的ł、ą这些)。如果必须保留ANSI模式,那得把UTF-8转成波兰语专属的ANSI代码页CP1250:
// 先转成宽字符,再转成CP1250编码的ANSI字符串 int wideLen = MultiByteToWideChar(CP_UTF8, 0, pUtf8Content, nByteLen, NULL, 0); CString wideStr; MultiByteToWideChar(CP_UTF8, 0, pUtf8Content, nByteLen, wideStr.GetBuffer(wideLen), wideLen); wideStr.ReleaseBuffer(); int plAnsiLen = WideCharToMultiByte(1250, 0, wideStr, -1, NULL, 0, NULL, NULL); char szPlAnsi[512]; WideCharToMultiByte(1250, 0, wideStr, -1, szPlAnsi, plAnsiLen, NULL, NULL); AfxMessageBox(szPlAnsi);
确认波兰语的语言文件是正确的UTF-8编码:如果文件带BOM(开头三个字节0xEFBBBF),读取时要记得跳过这三个字节,否则转码后会出现一个奇怪的前缀字符;如果是无BOM的UTF-8,直接读取就行。
内容的提问来源于stack exchange,提问作者xMutzelx

