2010-03-06 16 views
5

Estoy utilizando el IME japonés como ejemplo, pero probablemente sea el mismo en otros idiomas que usan un IME para la entrada.C# e IME - obteniendo el texto de entrada actual

Cuando el usuario escribe texto en un cuadro de texto utilizando el IME, se activan los eventos KeyDown y KeyUp. Sin embargo, la propiedad TextBox.Text no devuelve el texto escrito hasta que el usuario haya validado la entrada en el IME utilizando la tecla Intro.

Entonces, por ejemplo, si el usuario escribe 5 veces あ valida, obtendré 5 eventos de keydown/keyup, con cada vez que TextBox.Text devuelva "" (la cadena vacía) y al final obtendré una clave/keyup para la tecla enter y TextBox.Text se convertirá directamente en "あ あ あ あ あ".

¿Cómo puedo obtener la entrada del usuario mientras el usuario está escribiendo, antes de que el usuario valide al final?

(sé cómo hacer esto en javascript en un campo > < de entrada en una página web, por lo que debe ser posible en C#!)

+1

¿Está en windows? En caso afirmativo, puede interceptar el Messsage WM_IME_COMPOSITION y usar ImmGetCompositionString para obtener la entrada del usuario. – Dian

Respuesta

7

Usted puede utilizar esto para conseguir la composición actual. Esto funcionará en cualquier estado de composición, y para japonés, chino y coreano. Solo lo he probado en Windows 7, por lo que no estoy seguro si funcionará en otras versiones de Windows.

En cuanto a las cosas son las mismas, bueno, las cosas son terriblemente diferentes entre los tres.

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); 
      } 
     } 
    } 
} 

Otras implementaciones que he visto utilizaron un StringBuilder, pero es mucho mejor usar una matriz de bytes, debido a que el SB por lo general terminan con un poco de basura en él también. La matriz de bytes está codificada en UTF16.

Y generalmente, querrá llamar a GetComposition cada vez que reciba un mensaje "WM_IME_COMPOSITION" como dijo Dian.

Es muy importante llamar a ImmReleaseContext después de llamar a ImmGetContext, por lo que está en un bloque finally.

+0

(Y) Gracias hombre. –

Cuestiones relacionadas