3

这是什么是在 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_PACKETWM_CHAR—直接从消息中生成一个LPARAM
  • VK_PROCESS— 调用一个函数ImmTranslateMessage(),该函数似乎是特定于葡萄酒的函数或未记录的 imm32.dll 函数;我分不清哪个是真的

而且 wine 也与WM_KEYUPand无关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+ 上您会这样做,但似乎插入字符的按键不会影响释放,因此无论如何它们都不会被处理,至少对于我尝试过的输入法(可能有一些……)。话虽如此,如果我错过了什么,我添加了另一个子问题。

4

1 回答 1

1

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

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

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

于 2017-01-03T20:55:21.253 回答