【发布时间】:2019-06-26 08:14:43
【问题描述】:
我正在开发一个应用程序,它接收以 UTF-8 编码的文本并需要在某些 MFC 控件上显示它。该应用程序是使用多字节字符集 (MBCS) 构建的,我们假设这无法更改。
我希望如果我将接收到的文本从 UTF-8 转换为宽字符字符串,我将能够使用 SetWindowTextW 方法正确显示它。为了尝试这个,我使用了一个玩具应用程序,它从文件中读取输入并设置我的控件的文本。
std::wstring utf8_decode(const std::string &str)
{
if (str.empty()) return std::wstring();
int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
std::wstring wstrTo(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
return wstrTo;
}
BOOL CAboutDlg::OnInitDialog()
{
std::vector<std::string> texts;
texts.resize(6);
std::fstream f("D:\\code\\sample-utf8.txt", std::ios::in);
for (size_t i=0;i<6;++i)
std::getline(f, texts[i]);
::SetWindowTextW(GetDlgItem(IDC_BUTTON1)->m_hWnd, utf8_decode(texts[0]).c_str());
::SetWindowTextW(GetDlgItem(IDC_BUTTON2)->m_hWnd, utf8_decode(texts[1]).c_str());
::SetWindowTextW(GetDlgItem(IDC_BUTTON3)->m_hWnd, utf8_decode(texts[2]).c_str());
::SetWindowTextW(GetDlgItem(IDC_BUTTON4)->m_hWnd, utf8_decode(texts[3]).c_str());
::SetWindowTextW(GetDlgItem(IDC_BUTTON5)->m_hWnd, utf8_decode(texts[4]).c_str());
::SetWindowTextW(GetDlgItem(IDC_BUTTON6)->m_hWnd, utf8_decode(texts[5]).c_str());
return TRUE;
}
使用 MBCS 构建了玩具应用程序后,我没有得到我想要的东西。
这是否意味着当我使用 MBCS 构建时,没有希望对单个控件使用 unicode 文本?如果可能的话,你能给我一些指示吗?谢谢。
【问题讨论】:
-
由于 MFC 窗口是 MBCS,请改用
SetWindowTextA(),并像以前一样将 UTF-8 数据转换为 UTF-16,然后在传递之前使用WideCharToMultiByte(CP_ACP)将 UTF-16 转换为 MBCS到窗户。但是您最终可能会得到相同的结果,因为将 Unicode 转换为 MBCS 是有损的。这就是你不应该再使用 MBCS 的原因 -
您可能需要为窗口设置一个 unicode 字体——可以处理 unicode 字符。如果您只有一个对话框,您可以在代码中重新创建子窗口以删除旧的 MBCS 窗口并为这些子窗口使用 unicode 窗口。
-
您的代码应该可以正常工作。也许您的文本文件不是 UTF8。使用记事本检查编码。或者这是@JosephWillcoxson 指出的字体问题 - 对于 Windows Vista 及更高版本,将字体设置为
Segoe UI。 -
他说如果他将应用程序设为 Unicode,它就可以工作。那会告诉我文本文件可能没问题。如果控件中的字体不能处理 unicode,那么它可能有他看到的那个问题。
-
感谢您的提示。 @JosephWillcoxson 我会尝试您的建议以编程方式创建它们,这似乎是最好的选择。
标签: c++ unicode utf-8 mfc multibyte-characters