如何在C++的MessageBox中正确显示UTF-8编码字符?
解决MessageBox显示UTF-8越南语乱码问题
问题原因
Windows平台下,默认调用的MessageBoxA使用系统默认ANSI编码解析字符串,但API返回的错误信息是UTF-8编码,两者编码不匹配导致非ASCII字符(如越南语)显示异常。需要将UTF-8字符串转换为Windows原生支持的UTF-16(宽字符)格式,再调用Unicode版本的MessageBoxW。
解决方案
提供两种UTF-8转UTF-16的实现方式,任选其一即可:
方法1:使用Windows API MultiByteToWideChar
这是Windows平台通用方案,无需依赖C++标准库特定实现:
#include <windows.h> std::wstring Utf8ToUtf16(const std::string& utf8Str) { if (utf8Str.empty()) return L""; // 获取所需宽字符缓冲区大小 int wideCharCount = MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, nullptr, 0); if (wideCharCount == 0) return L""; std::wstring utf16Str(wideCharCount, 0); MultiByteToWideChar(CP_UTF8, 0, utf8Str.c_str(), -1, utf16Str.data(), wideCharCount); // 移除自动添加的末尾空字符 utf16Str.pop_back(); return utf16Str; }
方法2:使用C++标准库 std::wstring_convert
适用于支持C++11及以上的编译器(如VS、GCC):
#include <locale> #include <codecvt> std::wstring Utf8ToUtf16(const std::string& utf8Str) { std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter; try { return converter.from_bytes(utf8Str); } catch (const std::range_error&) { return L""; } }
修改后的登录函数代码
替换原MessageBox调用为转换后的宽字符版本:
bool Request::Login() { std::string json = "{ \"email\": \"" + std::string(User::GetUsername()) + "\", \"password\": \"" + std::string(User::GetPassword()) + "\" }"; auto res = client->Post("/api/client/auth/login", json, "application/json"); if (res && res->status == 200) { auto j = nlohmann::json::parse(res->body); int indent = 4; std::string s = j.dump(indent); return true; } else { auto j = nlohmann::json::parse(res->body); std::string err = j["error"]; // 转换UTF-8到UTF-16 std::wstring errWide = Utf8ToUtf16(err); // 调用Unicode版本弹窗 MessageBoxW(NULL, errWide.c_str(), L"Error", MB_OK); return false; } }
额外注意事项
- 若项目默认使用Unicode字符集(VS项目属性中“字符集”设为“使用Unicode字符集”),可直接调用
MessageBox(编译器会自动映射到MessageBoxW)。 - 转换时需处理无效UTF-8编码的情况,避免程序崩溃。
内容的提问来源于stack exchange,提问作者Nguyen Van Cao Ky
相关产品推荐
相关产品推荐

