【问题标题】:How to change the CP_ACP(0) of windows ANSI apis in an application?如何在应用程序中更改 windows ANSI apis 的 CP_ACP(0)?
【发布时间】:2012-02-20 11:21:55
【问题描述】:

我尝试使用只有 ANSI 版本封装的 windows ANSI api 接口的 dll 库来绘制文本,但我需要使用 utf-8 存储字符串数据。我不想使用 MultiByte/WideChar 函数转换字符串,所以我想要一种方法来更改我的应用程序中的 CP_ACP,以便我可以将字符串数据输入 ANSI api。谢谢。

ps:我不想更改系统默认代码页。

【问题讨论】:

  • 我建议您至少为此添加一个语言标签。框架标签也会很有用。
  • 那里没有语言。 C++?
  • 但是已经有5个标签了,不能再添加标签了。
  • 无法更改单个进程的CP_ACPCP_ACP 是系统范围的设置。
  • 我以为我说“没有办法为单个进程更改 CP_ACP。”

标签: c++ winapi unicode utf-8 codepages


【解决方案1】:

CP_ACP 代表系统 Ansi 代码页。您不能在每个进程或每个线程的基础上更改它。这是一个系统范围的设置。如果 DLL 确实在内部依赖于 CP_ACP,那么您别无选择,只能在与 DLL 交互时将您的 from/to UTF-8 转换。

【讨论】:

    【解决方案2】:

    从 Windows 10 v1903 开始​​,您可以使用应用程序清单为给定进程设置活动代码页,这可能与系统范围的代码页不同:

    <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
      <assemblyIdentity type="win32" name="..." version="6.0.0.0"/>
      <application>
        <windowsSettings>
          <activeCodePage xmlns="http://schemas.microsoft.com/SMI/2019/WindowsSettings">UTF-8</activeCodePage>
        </windowsSettings>
      </application>
    </assembly>
    

    显然,如果您需要支持旧版本的 Windows,应用程序必须仍然知道 CP_ACP 可能不是 CP_UTF8 并自行执行任何必要的转换。

    更多详情请见Microsoft Docs

    【讨论】:

      【解决方案3】:

      UTF8 不是代码页,由于代码页仅对 ANSI 函数有意义,因此您无法按照您的要求进行操作。

      如果要将字符串存储为 UTF8,则需要使用 MultiByteToWideChar() 将应用程序的 ANSI 转换为 unicode(宽字符),然后使用 WideCharToMultiByte() 转换为 UTF8。

      或者,更新您的应用以在内部使用 unicode/宽字符串,并根据需要进行转换。

      【讨论】:

      • UTF-8 本身不是代码页,但 Microsoft 确实有 UTF-8 的代码页 - 65001 - 用于 MultiByteToWideChar()WideCharToMultiByte() 功能(也有代码页用于UTF-7 和 UTF-16 也是如此)。
      • 它也适用于 SetConsoleCP()。嘎嘎就像一个代码页,它是一个代码页。
      • @HansPassant,告诉人们SetConsoleCP(65001) 可以将控制台输入代码页设置为 UTF-8,这是一种误导。我们需要强调的是,这在控制台主机中被严重破坏,它假设单字节代码页(或东亚语言环境的双字节)。如果我们尝试在 Windows 10 之前通过ReadFileReadConsoleA 读取非 ASCII 字符(即 2-4 个 UTF-8 字节),则读取成功,读取 0 字节(看起来像 EOF)。从 Windows 10 开始,它成功地将非 ASCII 字符替换为 NUL 字符("\x00"),这是无用的边界。
      • @HansPassant, SetConsoleCP 与是否可以(或应该)为进程更改CP_ACP 无关,而不是为系统更改它并需要重新启动。与一般的 Windows API 不同,控制台 API 不依赖于映射到每个进程并在 PEB 中引用为 AnsiCodePageDataOemCodePageData 的快速 ANSI/OEM 表。
      【解决方案4】:

      “如何更改 CP_ACP?” - “我不想(想要)更改系统默认代码页。”

      好吧,你必须选择。 CP_ACP 系统默认代码页。

      【讨论】:

      • 谢谢。有没有办法更改单个进程的代码页?
      • @legendlee:不,没有。有SetThreadLocale()SetThreadUILanguaage(),但它们操作的是语言ID,而不是代码页。 UTF-8 不是一种语言,它是一种 Unicode 编码。
      猜你喜欢
      • 1970-01-01
      • 2017-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多