这是 在 Windows 上的自定义控件中处理任意文本输入的正确、现代的方法是什么? WM_CHAR?注塑机? TSF?.
因此,在尝试了非 IME 布局(美国英语)、非 TSF IME(Windows XP DDK 中的日语 FAKEIME)和 TSF 文本服务(Windows 7 附带的任何内容)后,看来如果活动输入处理器配置文件不是 TSF 文本服务(也就是说,它是
TF_PROFILETYPE_KEYBOARDLAYOUT
),我仍然需要处理击键和 WM_CHAR
消息来进行文本输入。
我的问题是我的架构需要一种方式来告知它可以忽略当前的关键消息,因为它被转换为文本输入消息。它不关心这是发生在翻译之前还是之后;它只需要知道这样的翻译将会或已经发生。或者用伪代码术语来说:
// if I can suppress WM_CHAR generation and synthesize it myself (including if the translation is just dead keys)
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
if (WillTranslateMessage())
InsertChar(GenerateEquivalentChar());
else
HandleRawKeyEvent();
break;
// if I can know if a WM_CHAR was generated (or will be generated; for instance, in the case of dead keys)
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
if (!DidTranslateMessage())
HandleRawKeyEvent();
break;
case WM_CHAR:
case WM_SYSCHAR:
InsertChar(wParam);
break;
处理来自键盘或通过非 TSF IME 的文本输入的标准方法是让
TranslateMessage()
进行 WM_KEYDOWN
到 WM_CHAR
的翻译。然而,有一个问题:MSDN 说
如果消息是 WM_KEYDOWN、WM_KEYUP、WM_SYSKEYDOWN 或 WM_SYSKEYUP,则无论转换如何,返回值都非零。
这意味着我无法用它来确定是否发生了翻译。
在阅读了一些 Michael Kaplan 博客文章后,我想我可以使用
ToUnicode()
或 ToUnicodeEx()
自己进行转换,从 GetKeyboardState()
传入状态数组。 wine 源代码似乎同意,但它有两种特殊情况,我不确定它们是特定于 wine 的还是也需要在真实的 Windows 上完成:
VK_PACKET
— 直接从消息的 WM_CHAR
生成
LPARAM
VK_PROCESS
— 调用函数ImmTranslateMessage()
,该函数似乎是特定于 wine 的函数或未记录的 imm32.dll 函数;我分不清哪个是真的酒对
WM_KEYUP
和 WM_SYSKEYUP
也没有任何作用;再说一次,我不知道这是否只适用于葡萄酒。
但是我是否需要在使用 TSF 的程序中担心这些情况?如果我这样做,“官方”的方式是什么?即便如此,我会在
WM_KEYUP
/WM_SYSKEYUP
上做什么?我也需要将它们发送到ToUnicode()
吗?如果有 WM_KEYUP
,我是否还需要在窗口中捕获 WM_CHAR
?
或者我是否遗漏了任何 MSDN TSF 示例中都没有的东西,而这些示例将允许我让 TSF 来处理
TF_PROFILETYPE_KEYBOARDLAYOUT
处理器?我以为 TSF 做了透明的 IME 直通,但我对 FAKEIME 样本的实验表明情况并非如此......?我看到 Firefox 和 Chromium 也会检查 TF_PROFILETYPE_KEYBOARDLAYOUT
,甚至使用 ImmGetIMEFileName()
来查看键盘布局是否由 IME 支持,但我不知道在这些情况下它们是否真的会自行处理输入。 ..
我现在的最低版本是Windows 7。
谢谢。
更新这个问题的原始版本包括需要了解相关的
WM_KEYUP
;第二次查看我在其他平台上的等效代码时,这毕竟是不必要的,除了 TranslateMessage()
的详细信息之外;我相应地调整了问题。 (在 OS X 上,您甚至不向文本输入系统提供按键释放事件;在 GTK+ 上,您这样做,但似乎插入字符的按键不会影响释放,因此无论如何它们都不会得到处理,至少对于我尝试过的输入法(可能有一些可以...)。)话虽如此,如果我错过了某些内容,我会添加另一个子问题。
一般来说,尝试复制 Windows 内部结构并不是一个好主意。它很乏味、容易出错,而且可能会在没有通知的情况下发生变化。
我有权在 WM_KEYDOWN 处理程序中选取箭头键(和其他特定键)的编辑控件,并将其他所有内容传递给默认处理程序,这将(最终)生成 WM_CHAR 或 TSF 输入调用(如果您的控件支持) TSF,它应该)。
在不涉及 TSF 处理程序的情况下,您仍然需要 WM_CHAR。但是,您始终可以让 WM_CHAR 处理程序调用 ITextStoreACP::InsertTextAtSelection 方法。
我的架构需要一种方式来告知它可以忽略当前的关键消息,因为它已转换为文本输入消息
我相信你可以使用TranslateMessageEx,也许设置标志位1。