将 IME 放入自定义文本框中,从 Control 派生

Posted

技术标签:

【中文标题】将 IME 放入自定义文本框中,从 Control 派生【英文标题】:Putting IME in a custom text box, derived from Control 【发布时间】:2011-03-18 06:17:06 【问题描述】:

我在 C# .net 3.5 中创建了自己的单行文本框控件

我完全是从头开始编写的,包括我自己的选择代码、滚动、复制/粘贴等。它甚至可以选择从左到右的文本,但我从来没有使用过...

我遇到的问题是 IME(输入法编辑器)集成。 IME 在一定程度上确实有效,但我有一些问题。我在这里只列出其中一个。

通常,使用 TextBox,IME 结构在 TextBox 内呈现。但是,在我的控件中,IME 显示在屏幕的右下方。我尝试查看其他自定义控件,包括 SharpDevelop 中使用的那个。然而,这也有同样的问题。输入中文、日文或韩文会导致在屏幕右下角输入 IME。

我需要一些关于如何在我自己的文本框中完成此操作的指示,我查看了用于 IME 的 Windows API,但功能太多,我不知道从哪里开始。

那么,有什么想法吗?

如果任何代码示例使用 C++(托管/非托管)或 VB.net 就可以了。我可以很容易地移动它。

【问题讨论】:

【参考方案1】:

好吧,看起来 *** 上的 IME 专家并不多……或者没有人感兴趣。

不管怎样,我想通了。

基本上,我必须捕获以下 Windows 消息:

WM_INPUTLANGCHANGE = 0x51
WM_KEYUP = 0x101
WM_CHAR = 0x102
WM_CONVERTREQUESTEX = 0x108
WM_IME_STARTCOMPOSITION = 0x10D
WM_IME_ENDCOMPOSITION = 0x10E
WM_IME_COMPOSITION = 0x10F
WM_IME_SETCONTEXT = 0x281
WM_IME_NOTIFY = 0x282
WM_IME_CONTROL = 0x283
WM_IME_COMPOSITIONFULL = 0x284
WM_IME_SELECT = 0x285
WM_IME_CHAR = 0x286
WM_IME_REQUEST = 0x0288
WM_IME_KEYDOWN = 0x290
WM_IME_KEYUP = 0x291

我捕获了WM_KEYUPWM_CHAR,因为如果我在合成韩语字符的过程中单击某个位置,我不会收到合成消息,但我仍然需要将该字符添加到我的文本框中。这是一个奇怪的行为,我想知道这是否是一个错误。

一旦发生这种情况,韩国人、中国人和日本人之间的行为就会不同。

韩语真的很简单(不过我不确定汉字转换,因为我不知道如何使用它)。

基本上,对于所有语言,每当我收到 WM_IME_COMPOSITION 时,我必须在 Imm32.dll 中调用 ImmGetCompositionString,正如我在回答 this question 时所描述的那样。然后我将其显示为正在进行的合成,但不要将其添加到我存储的文本中。

组合字符串后,来自 Windows 的消息对于每个 IME 都是不同的。每次都可以从WM_IME_COMPOSITION消息中得到。

在韩语中,LParam 将只是 GCS_RESULTSTRWParam 将是输入的字符,我可以将其转换为 char

在日语中,“LParam”为GCS_RESULTREADSTR | GCS_RESULTREADCLAUSE | GCS_RESULTSTR0 | GCS_RESULTCLAUSE。我必须使用我从上一个 WM_IME_COMPOSITION 消息中存储的ImmGetCompositionString 的结果,因为此时它将是一个空字符串。

在中文中,LParam 将是GCS_RESULTREADCLAUSE | GCS_RESULTSTR0 | GCS_RESULTCLAUSE。和日文一样,除非之前存储的ImmGetCompositionString 为空,在这种情况下我需要将WParam 转换为字符。

在所有三种情况下,我都必须确保清除显示的正在进行的比赛。

如果我收到WM_IME_STARTCOMPOSITION,我会设置一个合成标志(并显示正在合成的字符串)

如果我收到WM_IME_ENDCOMPOSITION,我会清除该标志(并清除正在进行的合成字符串)。

有时我没有收到WM_IME_ENDCOMPOSITION,所以我在收到WM_CHAR 时清除我的标记。


总而言之,这是一次非常有趣的学习体验,而且还在进行中 - 但 IME 现在终于可以在我的控制下使用了!我一直工作到凌晨 1 点才完成。

【讨论】:

刚刚找到***.com/questions/434048/how-do-you-use-ime,要是早点看到就好了! 嗨,我正在我的 WPF 应用程序中执行 AddHook 并提供 Wndproc。我在窗口启动时收到WM_IME_CONTEXT 消息,我捕获该消息并尝试通过将0 传递给lParam 然后调用本机DefWindowProc 来关闭默认的OS IME 组合窗口,但没有任何反应。带有绿色箭头的 IME composition 输入 ui 仍然显示。您能否发布一个关于您如何使其内联的sn-p?

以上是关于将 IME 放入自定义文本框中,从 Control 派生的主要内容,如果未能解决你的问题,请参考以下文章

Android IME:显示一个自定义弹出对话框(如 Swype 键盘),可以在 TextView 中输入文本

C# 和 IME - 获取当前输入文本

VC6.0中 如何将 LIST control中的信息读取到文本编辑框中

编辑文本框中提示的自定义位置。

如何从文本框中获取特定文本并传输到另一个文本框?

如何在文本框中显示全局 [静态] 变量的内容?