MFC 控件上的文本 - Unicode 字符(例如日语)被截断

2024-03-25

背景

我正在开发一个 C++/MFC 应用程序,我们已经将其转换为显示 unicode 字符以支持外语。在大多数情况下,这是成功的并且 unicode 字符显示正确。但我遇到了一个问题,某些控件上的某些文本被截断。

Example

在这里,您可以看到一个应该显示“ログuaト/终了”的按钮,但被切断并在其位置显示未知字符。

但如果我用空格填充字符串,它会显示正常。所需的空格数量因字符串而异。该字符串需要4个空格才能正确显示,而另一个少一个字符的字符串则需要5个空格;似乎与所需空间的数量没有相关性或模式。而且,我不想在整个代码中随机填充字符串,特别是当其他语言根本不需要它时。

我尝试过的(不起作用)

  • 缩小字体大小
  • 调整控件大小
  • 更改字体名称
  • 更改字体字符集
  • 从应用程序中不存在此问题的另一个控件复制控件属性
  • 添加额外的空终止符
  • 使用零宽度字符填充
  • 使用SetWindowTextW
  • 更改源和执行字符集
  • 更改系统区域设置

我发现唯一有效的方法是填充任意数量的空格,这当然不是理想的解决方案。

其他信息

  • 我只注意到日语字符的这个问题,但只测试了英语、德语和日语。
  • 日语字符使用 3 个字节的数据,我怀疑这与此有关,但我不知道是什么或为什么。英语字符使用 1 个字节,某些德语字符使用 2 个字节。
  • 一个地方的控件(按钮/标签/等)可能会出现问题,而位于不同位置且包含相同文本的控件则不会出现问题,即使它们都是按钮等。
  • 当文本被截断时,它通常会在末尾显示一个问号框(如第一张图像)或一个随机字符/字母。每次运行应用程序时,该字符都会发生变化,但问题框是最常见的。
  • 对于我的填充“修复”,空格位于字符串的开头还是结尾并不重要,只要空格数量足够即可。它也不需要是空格,任何非零宽度字符都可以。
  • 使用 MBCS(多字节字符集)编译并启用 Windows 10 UTF-8 Unicode 支持设置。 (与使用定义的 UNICODE 进行编译相反,这不是一个选项。大型旧代码库)

EDIT:这是如何设置文本的示例

GetDlgItem(IDC_SOME_CTRL_ID)->SetWindowText(GetTranslation("Some String"));

其中 GetTranslation() 是我们自己的函数,用于查找“Some String”的翻译(基本上是一个查找表)并返回一个 CString。使用调试器我可以看到返回的 CString 始终具有正确的字符串值。我可以用硬编码的日语字符串替换 GetTranslation,但问题仍然会发生。

EDIT 2:我收到抱怨说这段代码不够。

myapp.rc

// Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
#include "afxres.h"
#undef APSTUDIO_READONLY_SYMBOLS

IDD_VIEW_MENU DIALOGEX 0, 0, 50, 232
STYLE DS_SETFONT | WS_CHILD
FONT 14, "Verdana", 0, 0, 0x1
BEGIN
    CONTROL         "btn0",IDC_BUTTON_MENU_0,"Button",BS_3STATE | BS_PUSHLIKE,12,38,25,13
END
#endif

资源.h

#define IDC_BUTTON_MENU_0             6040

视图菜单.cpp

#include "stdafx.h"
#include "ViewMenu.h"

CViewMenu::CViewMenu() : CFormView(CViewMenu::IDD)
{
}

void CViewMenu::DoDataExchange(CDateExchange* pDX)
{
    CFormView::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_BUTTON_MENU_0, m_ctrlMenuButton0);
}

void CViewMenu::OnInitialUpdate()
{
    CFormView::OnInitialUpdate();
}

void CViewMenu::OnDraw(CDC* pDC)
{
    CFormView::OnDraw(pDC);

    GetDlgItem(IDC_BUTTON_MENU_0)->SetWindowText("ログアウト/終了");

    return;
}

查看菜单.h

#include "resource.h"

class CViewMenu : public CFormView
{
    protected:
        CViewMenu();

    public:
        enum { IDD = IDD_VIEW_MENU };
        CButton m_ctrlMenuButton0;
}

无论默认系统区域设置如何,以下内容都应在 Windows 10 版本 1903 及更高版本中工作,并满足 OP 的要求(字符串文字、MBCS 构建、无 Unicode 窗口等)。经验证,它可以在 2004 版本中工作,设置为En-US区域设置,不带“Beta:使用 Unicode UTF-8 提供全球语言支持” 已检查,使用 VS 2019 16.7.5 构建。

  • 以 UTF-8 编码(带或不带 BOM)保存包含活动代码页之外的字符的源文件。

  • 编译用_MBCS定义(在 IDE 中:属性/高级/字符集= MBCS)。

  • 编译/utf-8 https://learn.microsoft.com/en-us/cpp/build/reference/utf-8-set-source-and-executable-character-sets-to-utf-8?view=msvc-160转变 (C/C++ / 命令行 / 附加选项=/utf-8)。

  • 创建一个清单文件,声明 UTF-8 作为进程的目标代码页(根据activeCodePage文档 https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests#activecodepage).

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
      <asmv3:application>
        <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">
          <activeCodePage>UTF-8</activeCodePage>
        </asmv3:windowsSettings>
      </asmv3:application>
    </assembly>
    
  • 将清单文件添加到项目中(在 IDE 中:清单工具/常规/输入和输出/附加清单文件= 在上一步中创建的清单文件)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MFC 控件上的文本 - Unicode 字符(例如日语)被截断 的相关文章

  • 如何验证文本文件中的用户名和密码? | Winforms C#

    首先我制作了textbox1 用于用户名 textbox2 用于密码 和button1 检查 后 private void button1 Click object sender EventArgs e FileStream fs new
  • ToLookup 是否强制立即执行序列

    我正在调查可枚举 ToLookup将可枚举序列转换为字典类型数据结构的 API 更多详情可在这找到 https msdn microsoft com en us library system linq enumerable tolookup
  • 将一个文件写入.c中的另一个文件

    我有一个读取文件然后将其内容复制到另一个文件的代码 我需要使其仅复制每 20 个符号 然后跳过 10 个符号 然后再次跳过 20 个符号 依此类推 我必须使用 lseek 函数 但我不知道如何将所有这些放入循环中来执行此操作 main ar
  • Request.Url.Port 给出错误的端口

    我的支持团队为我提供了一个 Live IP 例如http 201 121 152 168 68 现在在正常情况下你会认为68是端口 但是 当我执行 Request Host 时 我得到201 121 152 168当我执行 Request
  • Control.Invoke 在隐藏的 ShowDialog 中“卡住”

    我有解决这个问题的方法 但这不是我第一次被咬 所以我试图确切地了解发生了什么 从我的申请中 我ShowDialog表单 表单上有一个按钮 单击该按钮时会调用另一个 非 GUI 线程上的代码 非 GUI 线程发回状态 Pushed then
  • 在R包/.Rd文件中搜索unicode字符

    如何在 R 包或特定文件中搜索特定的 unicode 字符 我使用的是 RStudio IDE 我正在尝试向 CRAN 提交包裹 所有检查均通过 但以下情况除外 W checking PDF version of manual 49 5s
  • 时间:2019-03-17 标签:c++rapidjson返回值

    我在我的项目中使用rapidjson 我有一个方法可以解析 json 并返回其中的一部分 static rapidjson Document getStructureInfo std string structureType rapidjs
  • Windows 10 ScrollIntoView() 不会滚动到列表视图中间的项目

    我有一个包含 20 个项目的列表视图 我想以编程方式滚动列表视图 ListView ScrollIntoView ListView Items 0 将滚动列表视图到第一项 ListView ScrollIntoView ListView I
  • 私有方法和属性的 JetBrains Rider C# 命名风格

    我想将私有方法的首字母设为小写 将公共方法的首字母设为大写 然而 在 Rider 中 C 命名风格下似乎只有一个选项可以应用所有方法 属性和事件 告诉 Rider 仅对私人使用不同约定的最佳方式是什么 也可以看看 私有方法和属性的 ReSh
  • 如何使用SQL Server CE的动态连接字符串?

    我在 Windows 应用程序中使用 SQL Server CE 4 0 并使用实体框架创建它的模型 它工作正常 但我的问题是它没有构造函数来更改连接字符串 并且默认情况下它从app config file using var Contex
  • DISM.exe 返回代码?

    我有一个程序调用 dism exe 程序 它在后台运行一些命令 现在 我只检查返回代码 0 或其他任何内容 以显示进程失败或成功 我可以用什么来交叉检查返回代码以获得准确的返回错误 DISM 参考了哪些回报 评论中提供的链接DISMAPI
  • 执行按钮单击时使 wpf UI 响应

    在我的 wpf c 应用程序中 当用户按下按钮时会执行一个很长的过程 当按下按钮直到执行完整的代码时 窗口将冻结 用户无法在窗口中执行任何其他任务 如何使按钮单击代码作为后台进程 以便窗口响应用户 我尝试过以下方法 但没有成功 privat
  • 将 JSON 转换为数据表

    我有以下格式的 JSON id 10 name User add false edit true authorize true view true id 11 name Group add true edit false authorize
  • 指向数组的指针 int (*ptr)[]

    我想了解指向数组的指针如何工作 代码片段 include
  • 如何只应用一种 clang-format 操作?

    我想用clang 格式调整我的评论 但仅此而已 选项是 AlignTrailingComments bool 但是当我运行以下命令时 clang format 3 6 i style AlignTrailingComments true
  • 虚拟继承 - 跳过构造函数

    我有以下课程 class Socket Socket Socket SOCKET s class Connection public virtual Socket Connection IP ip 这两个类包含一些纯虚函数和一些非虚函数以及
  • C 中的静态和外部内联函数[重复]

    这个问题在这里已经有答案了 我正在尝试详细了解静态函数和外部函数之间的区别 我知道静态内联函数和外部内联函数之间的基本区别 我的理解如有错误请指正 静态内联函数仅对定义它的翻译单元可见 外部内联函数可以在多个翻译单元中访问 最好在头文件中定
  • 检测 Windows 重新启动是否是由于 Windows 更新造成的

    我的电脑上的一些应用程序一直在检测 Windows 更新是否重新启动 这是可以观察到的 因为它们会在 Windows 更新自动重启后重新启动 这非常有帮助 因为这些应用程序会重新加载更改 甚至unsaved更改或恢复选项卡 如果是浏览器 执
  • 警告 C4172:返回局部变量或临时变量的地址[重复]

    这个问题在这里已经有答案了 可能的重复 指向局部变量的指针 https stackoverflow com questions 4570366 pointer to local variable 我在这个网站上阅读了很多关于同一问题的其他主
  • exit() 和 abort() 有什么区别?

    在C和C 中 有什么区别exit and abort 我试图在发生错误 不是例外 后结束我的程序 abort http en cppreference com w c program abort退出程序而不调用使用注册的函数atexit h

随机推荐

  • sizeof(x) 和 sizeof(p_x) 之间有什么区别

    你能告诉我两者有什么区别吗sizeof x and sizeof p x 在下面的代码中 int x 10 p x p x int malloc 10 sizeof int sizeof x 给出数组使用的字节数x sizeof p x 给
  • 程序退出时如何删除文件? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 有没有办法注册一个文件 以便在Python退出时将其删除 无论它如何退出 我正在使用长期存在的临时文件 并希望确保它们被清理 该文件必
  • 启动屏幕故事板迁移问题

    我有一个用 Objective C 构建的应用程序 它使用启动屏幕图像集作为启动画面 根据最近苹果公司的新指南 适用于 iPhone 或 iPad 的应用程序必须使用 iOS 13 SDK 或更高版本构建 并且 使用 Xcode 故事板提供
  • 如何检查同一个java程序的两个实例是否正在运行?

    您好 我正在制作一个将通过 javaw exe 运行的程序 因此它不直接可见 现在我的问题是有时 意外地 用户可能会运行同一应用程序的多个实例 例如输入javaw myProgram两次 在这种情况下 如果程序已经在运行 有什么方法可以阻止
  • Bootstrap Popover 一键点击即可工作 - JavaScript

    我有一些引导按钮 单击按钮时应该显示一个弹出窗口 usernameL onclick function e e currentTarget id popover html true 当网站加载并且我第一次单击按钮时 没有任何反应 如果我第二
  • AlamoFire 在后台会话中下载

    我在新应用程序中使用 Alamofire 基于 Alamofire 的下载管理器示例 我需要一些有关使用后台会话下载文件的说明 我需要重写 SessionDelegate 才能使其正常工作吗 要不就backgroundCompletionH
  • NoClassDefFoundError:android.support.v7.widget.helper.ItemTouchHelper$3

    嗨 我想创建滑动删除RecyclerView结果是崩溃 看着那 这build gradle 我导入了所需的所有库 在代码中我可以使用ItemTouchHelper类但是当我想刷一个项目时它崩溃了 build gradle compile c
  • 在 groupby 之后将组与一个数据帧合并

    我试图回答这个问题 https stackoverflow com questions 47117982 insert missing category for each group in pandas dataframe通过组级合并 下面
  • 为什么只有当可执行文件在 Visual Studio 下运行时 CreateFileA 才会失败?

    我写了一个简单的check file ref函数使用 WinAPI 检查两个路径是否引用同一个文件 代码没问题 它是用 C 语言的 Visual Studio 2017 编译的 标志 TC 奇怪的是CreateFileA当可执行文件在 Vi
  • GPIO-Hog声明的目的和用途

    问题 其目的和用例是什么gpio hog宣言 可以从用户空间连接 占用 的 GPIO 引脚吗 如果 占用 GPIO 引脚无法与用户空间交互 那么是否有任何机制可以在 dts 文件中配置 GPIO 引脚以进行用户空间交互 背景 我正在尝试配置
  • 通过在两个现有列上使用 lambda 函数在 Panda 中创建新列

    我可以通过定义用户函数然后使用 apply 在 Panda 中添加新列 但是 我想使用以下方法来做到这一点lambda 有办法吗 例如 df有两列a and b 我想创建一个新专栏c这等于之间的最长长度a and b df pd DataF
  • Swift 结合添加运算符方法,如何使返回值简单、简短,如 Publishers.FlatMap.XX> 到 AnyPublisher

    当我添加一些运算符时 返回值会更长 例如 Publishers FlatMap 令牌 gt AnyPublisher gt 其实我希望用户只需要知道AnyPublisher足够 有什么办法让我只能返回AnyPublisher而不是Publi
  • Android动态功能模块依赖关系

    所以我有几个共享通用代码的功能 让我们称它们为 feature1 和 feature2 我无法将共享代码添加为 feature1 和 feature2 的依赖项 Android studio 抛出以下错误 多个 APK 打包同一库可能会导致
  • 找不到引用 Microsoft.DirectX.AudioVideoPlayback 和 Microsoft.DirectX

    我已经安装了 net 4 0 以及 XNA 4 0 前段时间我用过Microsoft DirectX播放一些音乐 现在当我尝试重做工作时 我找不到参考 平台上的新变化是否修改或移动了参考文献中的某些内容 视觉工作室 2010 右键单击项目
  • 如何使用preparedstatement获取最后插入行的id? [复制]

    这个问题在这里已经有答案了 我使用以下代码将新行插入数据库 我需要获取最后插入行的 id 但是当我运行代码时 它显示以下消息 SEVERE java sql SQLException Generated keys not requested
  • 加载后隐藏微调器

    我想在加载页面后隐藏微调器 我尝试过这个 document ready function loader hide Hide it initially ajaxStart function this show ajaxStop functio
  • 如何将 IsActiveAsync 失败信息传递给用户和客户端?

    In my IdentityServer4我实施的项目IProfileService The IsActiveAsync使用隐式和混合流时 在人类用户通过登录网页成功进行身份验证后 会多次调用该方法 我注意到它被调用时context Cal
  • 结构归纳终止

    我无法让 Agda 的终止检查器接受使用结构归纳定义的函数 我认为 我创建了以下最简单的示例来展示此问题 以下定义size被拒绝 即使它总是在严格较小的组件上递归 module Tree where open import Data Nat
  • DB 或 XML 问题

    XML 似乎是另一种以更小规模存储信息的方式 而DB可以处理所有类型 我有兴趣了解每种方法的优点和缺点 在某个场景中 其中一个更好吗 我确信每个人都有最好的情况 先感谢您 嗯 XML 是任何人都可以读取的文件 因为它是文本 数据库必须通过
  • MFC 控件上的文本 - Unicode 字符(例如日语)被截断

    背景 我正在开发一个 C MFC 应用程序 我们已经将其转换为显示 unicode 字符以支持外语 在大多数情况下 这是成功的并且 unicode 字符显示正确 但我遇到了一个问题 某些控件上的某些文本被截断 Example 在这里 您可以