如何控制WM_IME_CHAR中wParam的值类型

问题描述 投票:0回答:1

我正在开发一个在 Windows 10 上接收用户键盘输入的 C++ 程序。用户可以使用输入法和美式键盘输入英语和东亚语言(例如中文)。

当用户通过微软输入法输入中文时,程序会收到WM_IME_CHAR消息。它收到的 wParam 值在两台 Windows 10 计算机上有很大不同,具有相同的键盘输入和用户选择的相同输入法。

为了进行测试,用户在两台Windows 10计算机上的键盘上输入相同的汉字。在一台计算机上,wParam给出了一个GBK或GB2312编码的字符,我知道如何处理。在另一台计算机上,wParam 似乎总是一个小数字 63,我不知道它是什么。我找不到两台计算机之间的任何差异。据我所知,所有其他软件在两台计算机上的运行方式都是相同的。例如,记事本在两台计算机上的工作方式相同。

我的目标不是找出计算机设置的差异。我的目标是修复我的程序,以便它从两台计算机接收相同的正确输入,即使它们可能有不同的设置。

什么会影响 WM_IME_CHAR 消息的 wParam 中的值类型?如何通过 Win32 或 Windows API C/C++ 调用来控制它?

该程序是在 Visual Studio 2019 中构建的,针对 32 位 (x86) 平台。测试中使用的特定输入法是简体中文 - 微软拼音。

winapi ime
1个回答
0
投票

我在多台Windows 10计算机上调查并尝试了各种Windows API调用,最终得到了一个相对完整的答案和解决方案。我正在分享我发现的东西。

当用户通过 IME 从键盘输入东亚字符时,有 3 个因素会影响通过 WM_IME_CHAR 消息的 wParam 传递到程序中的值。因素有:

  • a) Windows 上“非 Unicode 程序的语言”设置 10 台
  • b) 窗口类如何注册,通过
    RegisterClass[Ex]A()
    RegisterClass[Ex]W()
  • c) WM_IME_COMPOSITION 是如何处理的 你的程序。

其中,软件开发者可以控制b)和c)。通过正确的编码,b) 和 c) 提供足够的控制,使您的程序正常工作,无论 a) 如何设置。

可通过控制面板访问上述 PC 设置。它在 Windows 系统中以两种方式标记,在显示窗格中标记为“非 Unicode 程序的语言”,在编辑对话框中标记为“系统区域设置”。我相信该设置不仅指定语言,还暗示了唯一的字符编码。这个概念对中文很重要,因为有多种编码。此设置是系统范围的,而不是针对每个用户的。要更改它,您需要管理员密码。如果更改设置,Windows 系统会立即要求输入系统密码重新启动。要找到该设置,您可以打开“控制面板”,然后打开“区域/管理”窗格,或者打开“设置”,然后打开“区域/时间和语言/区域/其他日期、时间和区域设置/区域/管理窗格”。

当“非 Unicode 程序的语言”设置为东亚语言且其编码覆盖用户输入时,如果您的程序通过

RegisterClassW()
RegisterClassExW()
注册窗口类,则 WM_IME_CHAR 的 wParam 会获取 Unicode输入字符的数量。如果您的程序通过
RegisterClassA()
RegisterClassExA()
注册,则 WM_IME_CHAR 的 wParam 会获取由“非 Unicode 程序的语言”设置选择的特定编码。

当“非 Unicode 程序的语言”设置为“英语(美国)”或任何编码不涵盖输入的语言时,并且用户通过 IME 输入东亚字符,WM_IME_CHAR 的 wParam 中的值取决于您如何注册该类以及如何处理 WM_IME_COMPOSITION 消息。如果 WM_IME_COMPOSITION 处理正确,并且您通过

RegisterClass[Ex]A()
注册,则 wParam 会获取 IME 的编码。如果您通过
RegisterClass[Ex]W()
注册,则 wParam 会获取 Unicode。如果没有正确处理 WM_IME_COMPOSITION 消息,wParam 就会出现“?”通过
RegisterClass[Ex]A()
RegisterClass[Ex]W()
来指示错误情况,无论您如何注册窗口类。

为了让你的程序无论“非 Unicode 程序语言”如何设置都能正常工作,你应该正确处理 WM_IME_COMPOSITION 消息。处理消息的最简单方法是将其传递给

DefWindowProcW()
函数。

根据我的测试,如果你正确处理 WM_IME_COMPOSITION,论坛讨论或文章中经常提到的其他一些事情并不重要。使用

GetMessageA()
GetMessageW()
,以及
DispatchMessage()
DefWindowProc()
的版本(对于所有其他消息)都没有关系。更重要的是,您不需要设置项目 Unicode(不需要定义 UNICODE 或 _UNICODE 宏)。但是,如果您将项目设置为 Unicode,则
DefWindowProc()
将指向
DefWindowProcW()
,从而正确处理 WM_IME_COMPOSITION 消息。

© www.soinside.com 2019 - 2024. All rights reserved.