5

例として日本語IMEを使用していますが、入力にIMEを使用する他の言語でもおそらく同じです。

ユーザーがIMEを使用してテキストボックスにテキストを入力すると、KeyDownイベントとKeyUpイベントが発生します。ただし、TextBox.Textプロパティは、ユーザーがEnterキーを使用してIMEへの入力を検証するまで、入力されたテキストを返しません。

たとえば、ユーザーが5回入力してから検証すると、5つのキーダウン/キーアップイベントが発生します。そのたびに、TextBox.Textは ""(空の文字列)を返し、最後にEnterキーのキーダウン/キーアップを取得します。キーとTextBox.Textは直接「あああああ」になります。

ユーザーが最後に検証する前に、ユーザーが入力しているときにユーザー入力を取得するにはどうすればよいですか?

(私はこれをWebページの<input>フィールドのjavascriptで行う方法を知っているので、C#で可能でなければなりません!)

4

1 に答える 1

7

これを使用して、現在の構成を取得できます。これは、どの構成状態でも機能し、日本語、中国語、韓国語でも機能します。Windows 7 でのみテストしたので、他のバージョンの Windows で動作するかどうかはわかりません。

物事が同じであるということに関しては、まあ、実際には3つの間で物事がひどく異なります.

using System.Text;
using System;
using System.Runtime.InteropServices;

namespace Whatever {
    public class GetComposition {
        [DllImport("imm32.dll")]
        public static extern IntPtr ImmGetContext(IntPtr hWnd);
        [DllImport("Imm32.dll")]
        public static extern bool ImmReleaseContext(IntPtr hWnd, IntPtr hIMC);
        [DllImport("Imm32.dll", CharSet = CharSet.Unicode)]
        private static extern int ImmGetCompositionStringW(IntPtr hIMC, int dwIndex, byte[] lpBuf, int dwBufLen);

        private const int GCS_COMPSTR = 8;

        /// IntPtr handle is the handle to the textbox
        public string CurrentCompStr(IntPtr handle) {
            int readType = GCS_COMPSTR;

            IntPtr hIMC = ImmGetContext(handle);
            try {
                int strLen = ImmGetCompositionStringW(hIMC, readType, null, 0);

                if (strLen > 0) {
                    byte[] buffer = new byte[strLen];

                    ImmGetCompositionStringW(hIMC, readType, buffer, strLen);

                    return Encoding.Unicode.GetString(buffer);

                } else {
                    return string.Empty;
                }
            } finally {
                ImmReleaseContext(handle, hIMC);
            }
        }
    }
}

私が見た他の実装では StringBuilder を使用していましたが、バイト配列を使用する方がはるかに優れています。バイト配列は UTF16 でエンコードされます。

通常、Dian が言ったように、"WM_IME_COMPOSITION" メッセージを受け取るたびに GetComposition を呼び出す必要があります。

ImmGetContext を呼び出した後に ImmReleaseContext を呼び出すことは非常に重要です。これが、finally ブロック内にある理由です。

于 2010-07-21T01:10:29.340 に答える