2010-03-06 8 views
5

Używam japońskiego edytora IME jako przykładu, ale prawdopodobnie jest taki sam w innych językach, które używają edytora IME do wprowadzania danych.C# i IME - pobieranie bieżącego tekstu wejściowego

Gdy użytkownik wpisze tekst w pole tekstowe za pomocą IME, zdarzenia KeyDown i KeyUp zostaną uruchomione. Jednak właściwość TextBox.Text nie zwraca wpisanego tekstu, dopóki użytkownik nie sprawdzi poprawności danych wejściowych w edytorze IME za pomocą klawisza Enter.

Na przykład, jeśli użytkownik wpisze 5 razy あ, to potwierdzi, otrzymam 5 zdarzeń keydown/keyup, za każdym razem TextBox.Text zwraca "" (pusty ciąg znaków), a na końcu otrzymam keydown/keyup dla klawisza Enter i TextBox.Text stanie się bezpośrednio "あ あ あ あ あ".

Jak mogę uzyskać dane wejściowe od użytkownika, gdy użytkownik pisze, zanim użytkownik sprawdzi poprawność na końcu?

(wiem, jak to zrobić w javascript na < wejściowego > polu na stronie internetowej, więc to musi być możliwe w języku C#!)

+1

Czy to w oknach? Jeśli tak, możesz przechwycić komunikat WM_IME_COMPOSITION i użyć ImmGetCompositionString, aby uzyskać dane wejściowe od użytkownika. – Dian

Odpowiedz

7

Można to wykorzystać, aby uzyskać aktualny skład. To zadziała w dowolnym stanie kompozycji oraz w języku japońskim, chińskim i koreańskim. Testowałem go tylko w systemie Windows 7, więc nie jestem pewien, czy zadziała w innych wersjach systemu Windows.

Jeśli chodzi o to, że wszystko jest takie samo, cóż, w rzeczywistości sytuacja wygląda zupełnie inaczej.

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

Inne implementacje Widziałem użył StringBuilder, ale jest znacznie lepiej użyć tablicy bajtów, ponieważ SB zazwyczaj skończyć z jakiegoś śmiecia w nim również. Tablica bajtów jest zakodowana w UTF16.

Zwykle chciałbyś wywołać funkcję GetComposition, gdy tylko otrzymasz komunikat "WM_IME_COMPOSITION", jak powiedział Dian.

Jest bardzo ważne, aby wywołać ImmReleaseContext po wywołaniu ImmGetContext, dlatego znajduje się on w bloku finally.

+0

(Y) Dzięki człowieku. –

Powiązane problemy