MFC CEdit 将非 ascii 字符转换为 ascii

Posted

技术标签:

【中文标题】MFC CEdit 将非 ascii 字符转换为 ascii【英文标题】:MFC CEdit converts non-ascii characters to ascii 【发布时间】:2019-05-22 11:04:43 【问题描述】:

我们有一个 MFC Windows 应用程序,最初使用 VC++ 6 编写,多年来针对更新的 IDE 进行了更新,目前在 VS2017 中开发。

应用程序是用 MBCS(不是 unicode)构建的。尝试切换到 Unicode 会导致 3806 编译错误,这可能只是冰山一角。

但是我们希望能够使用不同的代码页运行应用程序,即。 1250(中欧)。

我尝试构建一个小型测试应用程序,并设法让它使用特殊字符 (čćšđž)。我通过使用代码页 1250 将对话框字体设置为 Microsoft Sans Serif 来做到这一点。 我们的应用程序中的相同方法不起作用。注意:我们应用程序中的对话框是动态创建的,字体是使用 SetFont 设置的。

这两个应用程序中处理特殊字符的方式有所不同。

在测试应用程序中,特殊字符显示在编辑控件中,GetWindowsText 检索正确的字节。但是,尝试使用其他语言编写一些字符时,会将它们呈现为“????”。 在我们的应用程序中,所有特殊字符都正确呈现,但 GetWindowText(或 WM_GETTEXT)将特殊字符转换为类似的 ascii 对应字符 (čćđ -> ccd)。

我相信我们应用程序中的 Edit 控件显示 Unicode 文本,但 GetWindowText 将其转换为 ascii。

有谁知道这里发生了什么,以及我该如何解决?

注意:我知道如何将项目转换为 Unicode。我们目前选择不为此投入资源,因为它可能需要数周或数月才能实施。问题是我如何让它与 MBSC 一起使用,以及为什么编辑控件将 Č 转换为 C。

【问题讨论】:

如果这是您第一次尝试使用自己的窗口 API 编写代码页,那么也许您可以考虑使用 utf-8。或者,值得坚持使用 unicode 构建。您使用 char 的任何错误都只需更改为 tchar。但是代码页是一种糟糕的方式,因为您一次只支持一种语言,而且您所有的鸭子都必须以正确的顺序匹配。 将应用程序转换为 UNICODE 绝对是最佳选择,但根据您的代码,这可能或多或少有些麻烦。您可以做的第一件事是将所有字符串文字 "Abc" 替换为 _T("Abc") 并将所有 'X' 替换为 _T('X')。这可能已经消除了很多错误。然后摆脱所有char xx[yy] 并用CString 替换它们。有时您可能想保留char xx[yy],将它们替换为TCHAR xx[yy]。还将所有remaining strlen, strcpy`等替换为_tcslen_tcscpy等。将char替换为TCHAR。通常尽量使用尽可能少的原始字符数组。 IsWindowUnicode 的 备注 部分可能解释了为什么您会看到不同的结果。 @IInspectable 这听起来很有趣,我将在我的代码上调用 IsWindowUnicode 来检查这一点。 【参考方案1】:

我相信绝对有可能将应用程序移植到其他语言/代码页,您只需要修改 .rc(资源)文件,基本上每种语言都有一个资源文件,您可能更愿意这样做,因为菜单和/或字符串表中的字符串将使用不同的语言。就应用程序部分而言,这实际上是唯一需要的更改。

另一部分是您运行它的系统。窗口可以是 unicode 或非 unicode。您可以使用 Spyxx 实用程序看到这一点,它会告诉您窗口(过程)是否为 unicode(窗口属性,常规选项卡)。虽然 unicode 窗口确实可以正常工作,但非 unicode 窗口在获取或设置文本时必须从/到 unicode 和 mbcs 更改编码。转换基于系统(默认)代码页。这只能全局设置(对于整个机器),而不是每个应用程序或窗口。当然,仅设置字体的代码页是不够的(如果您在具有“正确”代码页的机器上运行应用程序,则根本不需要它)。也就是说,对于非 unicode 应用程序,只有一个代码页可以正常工作,其他代码页不会。

我可以看到两个选项:

如果您只需要更新少量控件,则可以仅将这些控件更改为 unicode,并使用“宽”版本的 get/set 窗口测试功能或消息 - 您必须在 unicode 和您想要的代码页之间转换文本。它需要编写一些代码,但具有转换独立于系统默认代码页的优点,例如,您可以将代码页放在某些配置文件、注册表中或作为命令行选项(在应用程序的快捷方式中)。有些控件类型可以更改为 unicode,有些则不能,因此请查看文档。将此技术成功地用于 mbcs 应用程序以多种不同语言显示/编辑翻译的字符串,但我只有一个控件,即 List-View,顺便说一句,它提供 LVM_SETUNICODEFORMAT 消息,因此即使在 mbcs 应用程序中也允许使用 unicode 文本. 最简单的方法是按原样运行应用程序,但它只能在具有正确默认代码页的机器上运行,就像大多数非 unicode 应用程序一样。

可以通过设置“非Unicode程序的语言”选项来更改系统默认代码页,该选项可在区域设置的“管理”选项卡中使用,并且需要重新启动。更改 Windows UI 语言也会更改此选项,但通过设置此选项,您无需更改 UI 语言,例如您可以拥有英语 UI 和东欧代码页。

查看非常相似的帖子here

【讨论】:

以上是关于MFC CEdit 将非 ascii 字符转换为 ascii的主要内容,如果未能解决你的问题,请参考以下文章

将非 ASCII 字符从 ASCII-8BIT 转换为 UTF-8

MFC输入框CEdit控件十六进制转换

Python3 - 将非 ascii 字符替换为其 unicode 代表值? [复制]

将非数字字符串转换为整数?

在 MFC 中,当 CEdit 控件达到最大字符时,退格不起作用

MFC的CEdit多于1024个字符自动换行