1

I want to know if I have completed an input word on a wpf textbox, but TextChanged event will fire even if I am typing in IME input. Therefore, I try to distinguish WM_IME_CHAR from WM_CHAR message (like I did in c++ windows form). I can get window message for a WPF window using this method, but how can I get the message specifically for a textbox inside WPF window?

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    HwndSource hwndSource = PresentationSource.FromVisual(myTextbox) as HwndSource;
    if (hwndSource != null)
    {
        hwndSource.AddHook(WndProc);
    }
}

private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    const int WM_CHAR = 0x0102;
    const int WM_IME_CHAR = 0x0286;
    switch(msg)
    {
        case WM_CHAR
            Console.WriteLine("WM_CHAR:" + wParam);
            //this is for testing
        case WM_IME_CHAR
            Console.WriteLine("WM_IME_CHAR" + wParam);
            //do something if myTextbox receive an IME char...
            break;
    }
    return IntPtr.Zero;
}

My above code cannot get any message for textbox. Is anything I am doing wrong?

EDIT:

I'm using VS2015 on windows 10.

If I focus on Window and type something in English, I can get WM_CHAR message and the correct wParam.

If I click on TextBox, I cannot get any WM_CHAR message.

If I focus on either Window or TextBox and type something in Chinese Input Method, I cannot get any message.

Dia
  • 851
  • 1
  • 15
  • 35
  • I don't have a convenient way to send `WM_IME_CHAR`, but otherwise the code above works fine for me. When I hook the `HwndSource` obtained from a `TextBox` instance, I get all the window messages for that object. You will need to provide more context, and a good [mcve] that reliably reproduces the problem, to understand better why this isn't working for you. – Peter Duniho Apr 14 '17 at 05:55
  • For what it's worth, in my tests I can get `WM_KEYDOWN` messages, but I never see `WM_CHAR` messages. It is possible that those messages are never dispatched to the `HwndSource` object. See https://stackoverflow.com/questions/7587052/whether-we-can-get-wm-ime-messages-when-we-re-typing-in-wpf-textbox-with-ime. The OP there states (without citing reference) that the `HwndSource` hook will not receive `WM_IME_CHAR` messages. – Peter Duniho Apr 14 '17 at 06:01
  • Seems the OP have the same issue. I tested to focus on `Window`, and can get `WM_CHAR` message, but not for `TextBox` – Dia Apr 14 '17 at 06:10
  • WM_CHAR is special. I think you have to do something non-trivial with IKeyboardInputSink. Surely there's a better way but you did not mention why you are trying to do this. – Hans Passant Apr 14 '17 at 08:34

2 Answers2

0

After google around, I found an article: imeで変換状態中でもtextbox-textchangedが発生する

Simply, I register three events:

TextCompositionManager.AddPreviewTextInputHandler(textBox1, OnPreviewTextInput);
TextCompositionManager.AddPreviewTextInputStartHandler(textBox1, OnPreviewTextInputStart);
TextCompositionManager.AddPreviewTextInputUpdateHandler(textBox1, OnPreviewTextInputUpdate)

So I could know a WM_IME_CHAR is typed when PreviewTextInputStart event is fired. When PreviewTextInput event is fired, I could know a word is completed.

Dia
  • 851
  • 1
  • 15
  • 35
0

I found another way in this answer to another question: https://stackoverflow.com/a/33105412/5665980

ComponentDispatcher.ThreadPreprocessMessage += (ref MSG m, ref bool handled) => {
        //check if WM_KEYDOWN, print some message to test it
        if (m.message == 0x100)
        {
            System.Diagnostics.Debug.Print("Key down!");
        }
    };

It should be noted that this technique will receive messages from every window that uses the current dispatcher, but you can filter by hwnd.

Rick Velde
  • 581
  • 6
  • 9