MessageBox描述仅显示单个字符,FormatMessage类型转换问题求助
问题解答:FormatMessage返回错误字符串仅显示单个字符
问题代码
std::string Window::Exception::TranslateErrorCode(HRESULT hr) noexcept { char* pMsgBuf = nullptr; DWORD nMsgLen = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPWSTR>(&pMsgBuf), 0, nullptr ); if (nMsgLen == 0) { return "Unidentified error code"; } std::string errorString = pMsgBuf; LocalFree(pMsgBuf); return errorString; }
问题原因
你的项目启用了Unicode字符集,此时FormatMessage会被预处理器自动替换为宽字符版本FormatMessageW。但你用char*类型的pMsgBuf,通过reinterpret_cast强制转为LPWSTR后,FormatMessageW会把宽字符数据写入char*指向的内存。宽字符(wchar_t)占2字节,比如第一个宽字符是L'X',内存中存储为0xXX 0x00,std::string会把0x00当作字符串结束符,因此只显示第一个字符。
另外直接传LPSTR报错,是因为FormatMessageW要求第五个参数是LPWSTR*类型,和LPSTR*类型不兼容导致的。
解决方案
方案一:使用ANSI版本FormatMessageA
直接调用ANSI版本的FormatMessageA,对应使用char*缓冲区,无需强制类型转换:
std::string Window::Exception::TranslateErrorCode(HRESULT hr) noexcept { char* pMsgBuf = nullptr; DWORD nMsgLen = FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPSTR>(&pMsgBuf), 0, nullptr ); if (nMsgLen == 0) { return "Unidentified error code"; } std::string errorString = pMsgBuf; LocalFree(pMsgBuf); return errorString; }
方案二:宽字符处理后转std::string(推荐)
在Unicode环境下,优先使用宽字符版本获取完整错误信息,再转换为std::string:
#include <locale> #include <codecvt> std::string Window::Exception::TranslateErrorCode(HRESULT hr) noexcept { wchar_t* pMsgBuf = nullptr; DWORD nMsgLen = FormatMessageW( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, hr, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPWSTR>(&pMsgBuf), 0, nullptr ); if (nMsgLen == 0) { return "Unidentified error code"; } // 将宽字符串转换为UTF-8编码的std::string std::wstring_convert<std::codecvt_utf8<wchar_t>> converter; std::string errorString = converter.to_bytes(pMsgBuf); LocalFree(pMsgBuf); return errorString; }
内容的提问来源于stack exchange,提问作者descreetOP
相关产品推荐
相关产品推荐

