在Windows上自定义控件中处理任意文本输入的正确,现代方法是什么? WM_CHAR? IMM? TSF?

时间:2016-11-06 18:49:48

标签: winapi input ime directwrite text-services-framework

我希望能够在自定义Windows控件中支持文本输入,就像EDIT和丰富的编辑控件已经做的那样,但不能将其中任何一个子类化。该控件目前使用Direct2D和DirectWrite绘制文本,并在带有平台更新或更新版本的Windows Vista SP1上运行(如果我认为我需要更新的Direct2D和DirectWrite功能,我可能会将其更改为带有平台更新的Windows 7 SP1或更新版本,假设这些是仅在那里或在Windows 8上可用,但这是一个不同的问题...)

对于它的价值,在OS X上我会使用NSTextInputClient而在GTK +上我会使用GtkIMContext。我正在谈论的就是这些事情。

显而易见的选择是使用WM_CHAR,如果我正确地收集,如果窗口类已在RegisterClassW()注册,则本机为UTF-16,因此应该"只是工作&#34 ;无论位置如何。但是,WM_CHAR生成TranslateMessage(),而its documentation表示无法确定是否已生成WM_CHAR,因为TranslateMessage()始终返回非零。我需要能够确定当前的键盘消息是否将由文本系统处理(因此应该被忽略);这尤其正确,因为所有非文本键都需要以与布局无关的方式处理(我已经拥有)。

我还在Windows 7示例代码中看到了IMM API和Text Services Framework。我不确定一个人是否比另一个好,他们似乎都做同样的事情。他们呢?

在IMM的情况下,有一些WM_IMM_xxx消息,我不确定我是否应该忽略,而且我发现的每个参考似乎都不同意是否应该在Unicode窗口中处理它们...另外,上述知道IMM是否处理某个键事件的问题仍然存在;有办法吗?

TSF有一个名为ACP的概念,它似乎允许我使用我想要的任何文本存储格式来存储我实际要使用的文本(即,不是正在进行的组合)。这是真的?我希望能够将我的文本存储为带有属性的UTF-8,在绘制时转换为UTF-16(对于DirectWrite)。其他API选择是否也允许我这样做?

还是我完全走错了路?

一旦我做完所有这些,我将如何opt into the on-screen keyboard

我使用的其他参考资料:

感谢。

更新 2016年11月7日
再次查看TsfPad示例后,我注意到它似乎也只是使用WM_CHAR;现在我不确定它是如何使用TSF的,除此之外......

1 个答案:

答案 0 :(得分:1)

TSF API是IMM API的超集。它也比IMM更新,是处理国际文本输入(以及手写和语音等其他输入机制)的当前现代方式。

如果您使用TSF API,则会通过API而不是Windows消息显示文本(因此问题与哪些消息无关)。

屏幕键盘会自动处理,您不必担心。 (TSF的全部目的是使您的应用独立于输入源。)

TSF 可以支持UTF-8,但这有点痛苦;您需要将扩展​​字符标记为隐藏。使用UTF-16会更好,这是TSF的默认API。

我所知道的关于如何向现有编辑控件添加TSF支持的最佳示例仍然是我在July 2007中写回的文章。

输入可以仍然通过WM_CHAR到达(例如,如果当前输入配置文件是键盘布局),所以你也需要实现它;但是,通常,您可以通过调用ITextStoreACP::InsertTextAtSelection实现来处理WM_CHAR消息。