由于 TranslateMessage() returns 无条件地非零,我怎么知道,无论是在事实发生之前还是之后,翻译已经发生?

Since TranslateMessage() returns nonzero unconditionally, how can I tell, either before or after the fact, that a translation has occurred?

这是 的延续。

因此,在尝试使用非 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_KEYDOWNWM_CHAR 的翻译。但是,有一个问题:MSDN 说

If the message is WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, or WM_SYSKEYUP, the return value is nonzero, regardless of the translation.

这意味着我不能用它来确定是否发生了翻译。

在阅读了一些 Michael Kaplan 的博文后,我想我可以使用 ToUnicode()ToUnicodeEx() 自己进行转换,从 GetKeyboardState() 传入状态数组。 The wine source code seems to agree,但它有两个特殊情况,我不确定它们是特定于葡萄酒的还是需要在真正的 Windows 上完成:

并且 wine 对 WM_KEYUPWM_SYSKEYUP 也没有任何作用;再一次,我不知道这是否只适用于葡萄酒。

但是在使用 TSF 的程序中,我什至需要担心这些情况吗?如果我这样做,"official" 的方法是什么?即便如此,我会在 WM_KEYUP/WM_SYSKEYUP 上做什么;我也需要将它们发送到 ToUnicode() 吗?如果有 WM_CHAR,我什至需要在我的 windows 中捕获 WM_KEYUPs 吗?

或者我是否遗漏了任何 MSDN TSF 样本中没有的东西,这些样本可以让我只让 TSF 处理 TF_PROFILETYPE_KEYBOARDLAYOUT 处理器?我以为 TSF 做了透明的 IME 直通,但我对 FAKEIME 样本的实验表明并非如此......?我看到 Firefox 和 Chromium 也检查 TF_PROFILETYPE_KEYBOARDLAYOUT 甚至使用 ImmGetIMEFileName() 来查看键盘布局是否由 IME 支持,但我不知道他们是否真的自己处理输入在这些情况下...

我现在的最低版本是 Windows 7.

谢谢。

UPDATE 这个问题的原始版本包括需要了解相关联的 WM_KEYUP;第二次查看我在其他平台上的等效代码时,这毕竟不是必需的,除了 TranslateMessage() 的细节;我已经相应地调整了问题。 (在 OS X 上,您甚至不向文本输入系统提供按键释放事件;在 GTK+ 上,您会这样做,但似乎插入字符的按键不会影响释放,因此无论如何都不会处理它们,至少对于我尝试过的输入法(可能会有一些...)。话虽这么说,如果我错过了什么,我添加了另一个子问题。

一般来说,尝试复制 Windows 内部构件不是一个好主意。它乏味、容易出错,并且可能会在不通知的情况下更改。

我拥有源代码访问权限的编辑控件可以在 WM_KEYDOWN 处理程序中选择箭头键(和其他特定键),并将其他所有内容传递给默认处理程序,这将(最终)生成 WM_CHAR 或 TSF 输入调用(如果您的控件支持 TSF,它应该支持)。

在不涉及 TSF 处理程序的情况下,您仍然需要 WM_CHAR。但是,您始终可以让 WM_CHAR 处理程序调用您的 ITextStoreACP::InsertTextAtSelection 方法。