将IME放在从Control派生的自定义文本框中

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

我从头开始写这个,包括我自己的选择代码,滚动,复制/粘贴等。它甚至可以选择从左到右的文本,而不是我曾经使用过的…

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

通常,使用TextBox,IME构造将在TextBox中呈现。 但是,在我的控制中,IME显示在屏幕的右下角。 我试着查看其他自定义控件,包括SharpDevelop中使用的控件。 但是,这也存在同样的问题。 键入中文,日文或韩文导致IME的内容在屏幕的右下角完成。

我需要一些关于如何在我自己的文本框中完成此操作的指针,我查看了Windows API for IME,但是有很多function,我不知道从哪里开始。

那么,有什么想法吗?

如果任何代码示例都在C ++(托管/非托管)或VB.net中,那就没问题。 我可以轻松地移动它。

好吧,看起来StackOverflow上没有很多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 ,因为如果我在合成韩文字符的中间点击某个地方,我不会收到合成消息,但我仍然需要将该字符添加到我的文本框中。 这是一种奇怪的行为,我想知道这是不是一个bug。

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

韩语是一个非常简单的(我不确定Hanja转换,因为我不知道如何使用它)。

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

当一个字符串被合成时,来自Windows的消息对于每个IME是不同的。 每次,我都可以从WM_IME_COMPOSITION消息中获取它。

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

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

在中文里, GCS_RESULTREADCLAUSE | GCS_RESULTSTR0 | GCS_RESULTCLAUSE将是GCS_RESULTREADCLAUSE | GCS_RESULTSTR0 | GCS_RESULTCLAUSE GCS_RESULTREADCLAUSE | GCS_RESULTSTR0 | GCS_RESULTCLAUSE GCS_RESULTREADCLAUSE | GCS_RESULTSTR0 | GCS_RESULTCLAUSE 。 它与日语相同,除非先前存储的ImmGetCompositionString为空,在这种情况下我需要将WParam转换为char。

在所有这三种情况下,我必须确保清除我正在显示的正在进行的补偿。

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

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

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


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