将 IME 放入源自 Control 的自定义文本框中

发布于 2024-09-11 01:24:01 字数 466 浏览 1 评论 0原文

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

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

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

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

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

那么,有什么想法吗?

如果任何代码示例是 C++(托管/非托管)或 VB.net 格式的,那就没问题。我可以轻松地把它移过去。

I have created my own single-line textbox control in C# .net 3.5

I've written this completely from scratch, including my own selection code, scrolling, copy/paste etc. It can even select left-to-right text, not that I'd ever use that...

The problem I'm having is with IME (input method editor) integration. The IME does work to an extent, but I have a few problems. I'll just list one of them here.

Normally, using a TextBox, the IME construction is rendered inside the TextBox. However, in my Control, the IME is displayed at the bottom right of the screen. I tried looking at other custom controls, included the one used in SharpDevelop. However, this had the same problem. Typing in Chinese, Japanese, or Korean caused the IME stuff to be done at the bottom-right of the screen.

I need some pointers on how to get this to be done in my own textbox, and I looked at the Windows API for IME, but there are so many functions, and I have no idea where to start.

So, any ideas?

It's fine if any code samples are in C++ (managed/unmanaged) or VB.net. I can move it across easily enough.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

难理解 2024-09-18 01:24:02

好吧,看起来 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,因为如果我单击合成韩语字符中间的某个位置,我不会收到一条撰写消息,但我仍然需要将该字符添加到我的文本框中。这是一个奇怪的行为,我想知道这是否是一个错误。

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

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

基本上,对于所有语言,每当我获得 WM_IME_COMPOSITION 时,我都必须在 Imm32.dll 中调用 ImmGetCompositionString,正如我在回答 此问题。然后,我将其显示为正在进行的合成,但不将其添加到我存储的文本中。

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

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

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

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

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

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

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

有时我收不到 WM_IME_ENDCOMPOSITION,因此我在接收 WM_CHAR 时清除标记。


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

OK, it looks like there aren't many IME experts on StackOverflow... or no one is interested.

Anyway, I figured it out.

Basically, I have to trap the following Windows messages:

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

I'm trapping WM_KEYUP and WM_CHAR, because if I click somewhere in the middle of compositing a Korean character, I do not get a composition message, but I need to add that character to my text box nonetheless. This is a weird behaviour, I wonder if it's a bug.

Once that happens, there are different behaviours between Korean, Chinese and Japanese.

Korean is a really easy one (I'm not sure about Hanja convert though, because I don't know how to use that anyway).

Basically, for all languages, whenever I get a WM_IME_COMPOSITION, I have to call ImmGetCompositionString in Imm32.dll as I have described in answer to this question. I then display this as a composition in progress, but don't add it to my stored text.

When a string has been composited the message from Windows is different for each IME. Each time, I can get it from the WM_IME_COMPOSITION message.

In Korean, LParam will simply be GCS_RESULTSTR, and WParam will be the entered character, which I can just cast to char

In Japanese 'LParam' will be GCS_RESULTREADSTR | GCS_RESULTREADCLAUSE | GCS_RESULTSTR0 | GCS_RESULTCLAUSE. I have to use the result of ImmGetCompositionString that I stored from the previous WM_IME_COMPOSITION message, because at this time it will be an empty string.

In Chinese, LParam will be GCS_RESULTREADCLAUSE | GCS_RESULTSTR0 | GCS_RESULTCLAUSE. It's the same as Japanese, except when the previously stored ImmGetCompositionString is empty, in which case I need to cast WParam to a char.

In all three cases, I have to make sure that my displayed comp in progress is cleared.

If I receive WM_IME_STARTCOMPOSITION, I set a compositing flag (and display the compositing string in progress)

If I receive WM_IME_ENDCOMPOSITION I clear that flag (and clear the compositing string in progress).

Sometimes I don't receive WM_IME_ENDCOMPOSITION, so I clear my flag on receiving WM_CHAR.


All in all, it was a very interesting learning experience, and one that is still in progress - but IME is now usable on my control, at last! I stayed at work till 1am to get it done.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文