2010-03-06 12 views
5

Ich verwende den japanischen IME als Beispiel, aber es ist wahrscheinlich das gleiche in anderen Sprachen, die einen IME für die Eingabe verwenden.C# und IME - Abrufen des aktuellen Eingabetextes

Wenn der Benutzer mithilfe des IME Text in ein Textfeld eingibt, werden die Ereignisse KeyDown und KeyUp ausgelöst. Die TextBox.Text-Eigenschaft gibt den eingegebenen Text jedoch erst zurück, wenn der Benutzer die Eingabe im IME mit der Eingabetaste bestätigt hat.

Also zum Beispiel, wenn der Benutzer 5 mal あ dann validiert, bekomme ich 5 keydown/keyup Ereignisse, wobei TextBox.Text jedesmal "" (die leere Zeichenfolge) zurückgibt und am Ende bekomme ich ein Keydown/key-up für die Eingabetaste und der TextBox.Text wird direkt "あ あ あ あ あ".

Wie kann ich die Benutzereingaben erhalten, während der Benutzer tippt, bevor der Benutzer am Ende validiert?

(Ich weiß, wie dies auf einem <Eingang> Feld auf einer Webseite in Javascript zu tun, so muss es in C#! Möglich)

+1

Ist es in Windows? Wenn ja, können Sie die Meldung WM_IME_COMPOSITION abfangen und ImmGetCompositionString verwenden, um die Benutzereingabe abzurufen. – Dian

Antwort

7

Sie diese verwenden können, bekommen die aktuelle Zusammensetzung. Dies funktioniert in jedem Kompositionszustand und für Japanisch, Chinesisch und Koreanisch. Ich habe es nur auf Windows 7 getestet, also nicht sicher, ob es auf anderen Windows-Versionen funktioniert.

Da die Dinge gleich sind, nun, die Dinge sind wirklich schrecklich anders zwischen den drei.

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

Andere Implementierungen Ich habe einen Stringbuilder verwendet gesehen, aber es ist viel besser, eine Byte-Array zu verwenden, da die SB wird in der Regel mit einigem Müll in ihm auch am Ende. Das Byte-Array ist in UTF16 codiert.

Und normalerweise würden Sie GetComposition aufrufen, wenn Sie eine "WM_IME_COMPOSITION" Nachricht wie Dian sagte.

Es ist sehr wichtig, ImmReleaseContext aufzurufen, nachdem Sie ImmGetContext aufgerufen haben, weshalb es in einem finally-Block ist.

+0

(Y) Danke Mann. –

Verwandte Themen