使用韩语键盘键入值时,为什么TextBox会更改事件触发三次?

时间:2016-10-26 18:08:35

标签: c# winforms textbox

我在电脑上使用韩语。如果我在TexBox控件中键入值TextBoxChanged事件触发了三次。我第一次得到打字的值,第二次我得到了空值,我得到了输入值。

如果有人知道原因。

提前致谢。

1 个答案:

答案 0 :(得分:1)

  

原因是韩国IME将跟踪击键并显示   中间人物。所以当我们让richtextbox输出其文本时   TextChanged事件,它将打破IME的工作

     

这确实是由于RichTextBox中的一个缺陷导致每次完成一个字符时导致IME输入模式退出,因为向IME发送WM_IME_COMPOSITION窗口消息导致其认为IME已完成。检索RichTextBox的Text属性时会触发此操作。   这是一个解决方法,它覆盖了RichTextBox窗口过程,以拦截和避免这个错误的韩文IME条目的代码路径,并使用Text的内部值来避免在IME处于合成中时调用基础控件的属性,但仍然在每个组合后更新输入字符。   请注意,该类公开了一个名为KoreanWorkaroundEnabled的bool属性,默认情况下为true。您可以将此设置为false以将行为恢复为默认值,如果您的文本输入语言是中文或日文,则必须使用该行为。在这些情况下,此解决方法将打破正常行为。您可以使用主机表单上的InputLanguageChanged事件根据当前输入语言设置属性:

    public Form1()
    {
        InitializeComponent();
        this.InputLanguageChanged += Form1_InputLanguageChanged;
    }

    void Form1_InputLanguageChanged(object sender, InputLanguageChangedEventArgs e)
    {
        if (!e.InputLanguage.Culture.TwoLetterISOLanguageName.Equals("ko"))
            richTextBoxKorean1.KoreanWorkaroundEnabled = false;
        else
            richTextBoxKorean1.KoreanWorkaroundEnabled = true;
    }
  

这是重写的RichTextBox类,它实现了   解决方法:

public class RichTextBoxKorean : RichTextBox 
{

    [DllImport("imm32.dll", CharSet = CharSet.Unicode)]
    private static extern int ImmGetCompositionString(IntPtr hIMC, uint dwIndex, byte[] lpBuf, int dwBufLen);

    [DllImport("imm32.dll", CharSet = CharSet.Unicode)]
    private static extern IntPtr ImmGetContext(IntPtr hWnd);

    [DllImport("imm32.dll", CharSet = CharSet.Unicode)]
    public static extern IntPtr ImmReleaseContext(IntPtr hWnd, IntPtr context);


    public enum WM_IME
    {
        GCS_RESULTSTR = 0x800,
        EM_STREAMOUT = 0x044A,
        WM_IME_COMPOSITION  =0x10F,
        WM_IME_ENDCOMPOSITION   =0x10E,     
        WM_IME_STARTCOMPOSITION     =0x10D
    }

    private bool skipImeComposition = false;
    private bool imeComposing = false;

    public bool KoreanWorkaroundEnabled = true;

    string _mText = "";

    protected override void WndProc(ref Message m)
    {
        if (KoreanWorkaroundEnabled)
        {
            switch (m.Msg)
            {
                case (int)WM_IME.EM_STREAMOUT:
                    if (imeComposing)
                    {
                        skipImeComposition = true;
                    }
                    base.WndProc(ref m);
                    break;

                case (int)WM_IME.WM_IME_COMPOSITION:
                    if (m.LParam.ToInt32() == (int)WM_IME.GCS_RESULTSTR)
                    {
                        IntPtr hImm = ImmGetContext(this.Handle);
                        int dwSize = ImmGetCompositionString(hImm, (int)WM_IME.GCS_RESULTSTR, null, 0);
                        byte[] outstr = new byte[dwSize];
                        ImmGetCompositionString(hImm, (int)WM_IME.GCS_RESULTSTR, outstr, dwSize);
                        _mText += Encoding.Unicode.GetString(outstr).ToString();
                        ImmReleaseContext(this.Handle, hImm);
                    }
                    if (skipImeComposition)
                    {
                        skipImeComposition = false;
                        break;
                    }
                    base.WndProc(ref m);
                    break;

                case (int)WM_IME.WM_IME_STARTCOMPOSITION:
                    imeComposing = true;
                    base.WndProc(ref m);
                    break;

                case (int)WM_IME.WM_IME_ENDCOMPOSITION:
                    imeComposing = false;
                    base.WndProc(ref m);
                    break;

                default:
                    base.WndProc(ref m);
                    break;
            }
        }
        else
            base.WndProc(ref m);
    }

    public override string Text
    {
        get
        {
            if (!imeComposing)
            {
                _mText = base.Text;
                return base.Text;
            }
            else
            {
                return _mText;
            }
        }
        set
        {
            base.Text = value;
            _mText = value;
        }
    }
}

https://social.msdn.microsoft.com/Forums/windows/en-US/cefa5376-7912-47f6-b86a-197a211c2b70/get-text-from-richtextbox-control-without-disturbing-ime-when-input-east-asian-language?forum=winforms