如何在 MFC 多字节应用程序中显示西里尔文字?
Posted
技术标签:
【中文标题】如何在 MFC 多字节应用程序中显示西里尔文字?【英文标题】:How to show Cyrillic text in MFC Multi-Byte application? 【发布时间】:2018-03-09 11:08:23 【问题描述】:我是 C++ 和 MFC 的新手。主要问题是我有一个需要翻译成俄语的 MFC 项目。我看到最好的选择是将项目更改为 Unicode,但我不能,因为这是一个巨大的项目,当我更改时,我收到超过 4000 个错误。稍后我们会将所有代码传递给 Unicode,但现在我只需要在按钮和 CListBox 上显示 Cyrillic。
嗯,主要是:如何用 Multibyte 打印 Cyrillic?
谢谢大家!
PD:抱歉,我会更明确地说明我的尝试:
使用俄语语言环境:
setlocale(LC_ALL, "russian_russia.1251");
setlocale(LC_CTYPE, "rus");
但是没有用。显示问号。
我还尝试使用函数 WideCharToMultiByte 进行转换。但显示的字符似乎编码错误。
std::string utf8_encode(const std::wstring &wstr)
if (wstr.empty()) return std::string();
int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
std::string strTo(size_needed, 0);
WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
return strTo;
wchar_t* wch = L"Привет";
std::string ch = utf8_encode(wch);
m_wndOutputBuild.AddString(ch.c_str()); //OUTPUT Привет
PD2:现在我这样打电话
setlocale(LC_ALL, "russian_russia.1251");
std::wstring wch = L"Привет";
std::string ch = encode_1251(wch);
m_wndOutputBuild.AddString(ch.c_str()); //OUTPUT Ïðèâåò
和功能:
std::string encode_1251(const std::wstring &wstr)
if (wstr.empty()) return std::string();
int size_needed = WideCharToMultiByte(1251, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
std::string strTo(size_needed, 0);
WideCharToMultiByte(1251, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
return strTo;
我发现 Windows-1251 将 CP 放在 WideCharToMultiByte here 上。
【问题讨论】:
我知道,***.com/questions/48558810/… 这对我不起作用,因为我无法更改为 Unicode,我的项目是一个巨大的项目。我也尝试使用语言环境,但没有做任何改变。显示问号。 @Treith:我是在previous answer 中建议您迁移到Unicode 的人,我仍然认为这是最好的方法。无论如何,如果您和您的团队确实想保留您的代码库 MBCS(“多字节”),我建议您从一个简单的基于 MFC 对话框的应用程序开始,然后在其中插入一个编辑控件和一个列表框.从编辑控件读取用户输入,并将用户输入的行添加到列表框中。使用CEdit::GetWindowText
从编辑控件读取用户输入,使用CListBox::AddString
填充LB。 ...
... 您应该会在列表框中看到用户输入的完全相同的字符串。如果你不这样做,那么在这里发布你的代码和确切的结果。从简单开始,并尝试找出您的确切问题。我不是 MBCS/Cyrillic 方面的专家,所以我无法提供更好的帮助。
嗨@Mr.C64,这不是我的帖子。只有一个示例解决方案在我的情况下不起作用。但是谢谢,我将从这个开始。
@Treith:我注意到您在问题中添加了更多详细信息和 C++ 代码 sn-p,因此我根据这些新信息添加了答案。
【参考方案1】:
在您的utf8_encode
函数中,将您的Unicode UTF-16 字符串转换为std::string
时,您将CP_UTF8
传递给WideCharToMultiByte
。然后你获取返回的 UTF-8 std::string
,并通过 .c_str()
将其传递给 CListBox::AddString
方法。
但是,如果您的应用程序使用 MBCS 西里尔文,您应该将 UTF-16 转换为您的 西里尔代码页,而不是 UTF-8,并将在您的西里尔代码页中编码的字符串传递给您的 MFC 类方法,例如 CListBox::AddString
。
换句话说,您可能希望用cyrillic_encode
函数替换您的utf8_encode
函数,该函数将UTF-16 文本作为输入,并将其转换为您的西里尔代码页:
// Convert from Unicode UTF-16 to Cyrillic code page
std::string cyrillic_encode(const std::wstring &utf16)
然后将返回的字符串传递给感兴趣的MFC类方法,例如:
// From Unicode UTF-16 to Cyrillic code page
std::string cyrillic_text = cyrillic_encode(wch);
// Show Cyrillic-encoded "MBCS" text
m_wndOutputBuild.AddString(cyrillic_text.c_str());
此外,正如 @IInspectable 在 cmets 中正确指出的那样,请考虑在转换函数中添加适当的错误检查代码。事实上,一般情况下,可能有 UTF-16 文本无法以西里尔文正确编码,因为后者是前者的真子集。
【讨论】:
检查WideCharToMultiByte
的返回值是否有错误可能也是一个好主意,和/或传递适当的标志以优雅地处理无法在目标字符集中表示的字符。另一种解决方案是构造一个CStringA
,使用conversion c'tor 采用wchar_t*
。我相信转换是使用调用线程的语言环境执行的。
@IInspectable 我同意。
嗨,我更新了代码。好的,我会检查退货。但似乎输出不正确。我是否在 Windows 上选择了主要语言西里尔文?
@Treith 我不知道。我没有使用西里尔文 Windows 的经验。我仍然相信你能做的最好的事情是在 Windows API/MFC 边界使用 Unicode UTF-16,并在边界从任何编码转换为 UTF-16,然后将 UTF-16 编码的文本提供给 Windows API 和MFC 包装器方法。以上是关于如何在 MFC 多字节应用程序中显示西里尔文字?的主要内容,如果未能解决你的问题,请参考以下文章
React组件中的JSX将西里尔文本显示为habra-codabra
MFC中,比如我要做一个管理系统,我得创建单文档,多文档,还是基于对话框。还是3个都可以。
MFC/VC 在多文档MDI程序中 子窗口初始最大化显示 如何去掉菜单栏右侧的最小化及向下还原按钮