2010-03-06 2 views
5

Я использую японский IME в качестве примера, но, вероятно, он аналогичен на других языках, которые используют IME для ввода.C# и IME - получение текущего текста ввода

Когда пользователь вводит текст в текстовое поле с использованием IME, запускаются события KeyDown и KeyUp. Однако свойство TextBox.Text не возвращает введенный текст, пока пользователь не проверит вход в IME с помощью клавиши Enter.

Так, например, если пользователь вводит 5 раз あ, то проверяет, я получу 5 событий keydown/keyup, каждый раз, когда TextBox.Text возвращает «" (пустая строка), а в конце я получу keydown/keyup для ключа ввода, а TextBox.Text будет непосредственно «あ あ あ あ あ».

Как я могу получить ввод пользователя во время ввода пользователем, прежде чем пользователь проверит его в конце?

(я знаю, как сделать это в JavaScript на < ввода > поля на веб-странице, так что это должно быть возможно в C#!)

+1

Это в окнах? Если да, вы можете перехватить WM_IME_COMPOSITION Messsage и использовать ImmGetCompositionString для ввода пользователя. – Dian

ответ

7

Вы можете использовать это, чтобы получить текущую композицию. Это будет работать в любом состоянии композиции, а также для японского, китайского и корейского языков. Я тестировал его только на Windows 7, поэтому не уверен, что он будет работать в других версиях Windows.

Что касается вещей, которые являются одними и теми же, ну, вещи на самом деле ужасно отличаются между этими тремя.

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, но гораздо лучше использовать байтовый массив, так как SB обычно в конечном итоге с какой-то мусор в нем, как хорошо. Массив байта кодируется в UTF16.

И обычно вы хотите вызвать GetComposition всякий раз, когда вы получаете сообщение «WM_IME_COMPOSITION», как сказал Диан.

Очень важно называть ImmReleaseContext после вызова ImmGetContext, поэтому он находится в конечном блоке.

+0

(Y) Спасибо человеку. –

Смежные вопросы