这是什么是在 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()
-to-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()
,该函数似乎是特定于葡萄酒的函数或未记录的 imm32.dll 函数;我分不清哪个是真的
而且 wine 也与WM_KEYUP
and无关WM_SYSKEYUP
;再说一次,我不知道这是否仅适用于葡萄酒。
但是在使用 TSF 的程序中,我什至需要担心这些情况吗?如果我这样做,那么“官方”的做法是什么?即便如此,我会在WM_KEYUP
/上做什么WM_SYSKEYUP
;我也需要把这些寄给ToUnicode()
吗?WM_KEYUP
如果有 s,我什至需要特别在我的窗口中捕捉sWM_CHAR
吗?
或者我是否遗漏了任何 MSDN TSF 示例中没有的东西,这些示例允许我让 TSFTF_PROFILETYPE_KEYBOARDLAYOUT
处理处理器?我认为 TSF 进行了透明的 IME 直通,但我对 FAKEIME 样本的实验显示其他情况......?我看到 Firefox 和 Chromium 也检查TF_PROFILETYPE_KEYBOARDLAYOUT
甚至用于ImmGetIMEFileName()
查看键盘布局是否由 IME 支持,但我不知道在这些情况下他们是否真的自己处理输入......
我现在的最低版本是 Windows 7。
谢谢。
更新这个问题的原始版本包括需要了解关联WM_KEYUP
的s;在第二次查看我在其他平台上的等效代码时,这毕竟不是必需的,除了 ; 的细节TranslateMessage()
。我已经相应地调整了问题。(在 OS X 上,您甚至不会向文本输入系统提供按键释放事件;在 GTK+ 上您会这样做,但似乎插入字符的按键不会影响释放,因此无论如何它们都不会被处理,至少对于我尝试过的输入法(可能有一些……)。话虽如此,如果我错过了什么,我添加了另一个子问题。