RichTextBox doesn't support Japanese IME when hosted in WinForms

10 posts, 0 answers
  1. Brian Seekford
    Brian Seekford avatar
    12 posts
    Member since:
    Jun 2009

    Posted 11 Jun 2015 Link to this post

    I tried hosting your WPF RichTextBox in a WinForms application and the Japanese IME doesn't work properly with it. I used the Microsoft IME and the characters start repeating themselves.

     

  2. Todor
    Admin
    Todor avatar
    168 posts

    Posted 12 Jun 2015 Link to this post

    Hi Brian,

    We are aware of such issue when RadRichTextBox is hosted in a WinForms application. The problem is in the default Caret class which handles the input in RadRichTextBox and the way the text input events are fired in that case. However, since our latest 2014 Q3 release, you can handle such scenarios and now you are able to define and plug in the RadRichTextBox your own custom Caret, which inherits the default one, so a workaround can be found. You can check our Custom Caret SDK example on that matter.
     
    For your convenience, I've created a sample demo with above mentioned changes and now the problem should be gone. You can find it attached. 
    Please note, that in the sample project, the used approach will works only when an IME is used, because we set the InputState property to Ime. If other input languages will be used (e.g. English), you should implement your own logic for the InputState setting.

    I hope this helps.
    If you have further questions, I'll be glad to assist you.

    Regards,
    Todor
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  3. UI for WPF is Visual Studio 2017 Ready
  4. Brian Seekford
    Brian Seekford avatar
    12 posts
    Member since:
    Jun 2009

    Posted 09 Jul 2015 in reply to Todor Link to this post

    Thanks.  I modified this a bit to also add support for Chinese as that also did not work.

     Do you plan on formally supporting Japanese and Chinese in this product? I imagine a lot of legacy applications will be using WPF hosted as transition work since full rewrites are generally out of budget.

     

    Also, I found this major error. Could you please provide guidance on a fix?

    Microsoft IME: Japanese: Hirigana

    Defect details: when typing Japanese with MS IME, need to hit space to change to Japanese character(still with dots under the characters), if type the next words, the previous ones disappeared.

    for example: I wanted to type 日本語は難しい(nihonngohamuzukasii), when type 'nihionngo', then hit space key, it will change to Japanese character(日本語) with dots under it, then if keep typing 'ha', it changed to は、but the previous 日本語 disappeared.                                                 

     Thanks.

     

     

  5. Tanya
    Admin
    Tanya avatar
    402 posts

    Posted 10 Jul 2015 Link to this post

    Hi Brian,

    Could you, please explain what do you mean when saying "formally supporting Japanese and Chinese"? We think that this is not a common case for using our controls and the workaround Todor suggested you is a good one.

    As to the behavior you are experiencing, I tried to reproduce it but to no avail. We are not specialists with the Japanese language, but I followed the steps you are describing and didn't observe the mentioned issue. For more clarity below I will list the exact steps I used. 

    1. I started the demo Todor sent you and switched to Japanese (Hirigana).
    2. Inserted "nihonngo" and hit Space - this results in 日本語.
    3. Inserted "hamuzukasii" and hit Space - the result is 日本語ほ難しい.

    Please check these steps and let me know if I am missing something.

    Regards,
    Tanya
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  6. Brian Seekford
    Brian Seekford avatar
    12 posts
    Member since:
    Jun 2009

    Posted 10 Jul 2015 in reply to Tanya Link to this post

    It happens after you type with the ime. Hit enter, go to another line then try the keys again. It causes the words to drop. I think I fixed the issue with a few changes and reflection. 

      class InternationalCaret : CustomCaret
        {
            private const string JapaneseName = "ja-JP";
            private const string Chinese = "zh";

            private bool isCurrentLanguageJapanese;
            private bool isCurrentLanguageChinese;

            public InternationalCaret()
            {
                InputLanguageManager.Current.InputLanguageChanged += this.Current_InputLanguageChanged;
                this.GotKeyboardFocus += this.OnGotKeyboardFocus;

                this.isCurrentLanguageJapanese = InputLanguageManager.Current.CurrentInputLanguage.Name == JapaneseName;
                isCurrentLanguageChinese = InputLanguageManager.Current.CurrentInputLanguage.Name.StartsWith(Chinese);
                this.Focusable = true;
            }

            private void UpdateImeState()
            {
                if (this.isCurrentLanguageJapanese)
                {
                    this.InputState =
                                      (InputMethod.Current.ImeConversionMode == (ImeConversionModeValues.Native | ImeConversionModeValues.FullShape | ImeConversionModeValues.Roman) ||
                                      InputMethod.Current.ImeConversionMode == (ImeConversionModeValues.Native | ImeConversionModeValues.FullShape | ImeConversionModeValues.Roman | ImeConversionModeValues.Katakana) ||
                                      InputMethod.Current.ImeConversionMode == (ImeConversionModeValues.FullShape | ImeConversionModeValues.Roman | ImeConversionModeValues.Alphanumeric)

                                      ) &&
                                      InputMethod.Current.ImeState == InputMethodState.On ?
                                      InputStates.Ime : InputStates.Standard;
                }
                else if (this.isCurrentLanguageChinese)
                {
                    this.InputState =
                                   ((InputMethod.Current.ImeConversionMode & ImeConversionModeValues.Native) == ImeConversionModeValues.Native
                                   ) &&
                                   InputMethod.Current.ImeState == InputMethodState.On ?
                                   InputStates.Ime : InputStates.Standard;
                }
                else
                {
                    InputState = InputStates.Standard;
                }
            }

            private void Current_InputLanguageChanged(object sender, InputLanguageEventArgs e)
            {
                this.isCurrentLanguageJapanese = e.NewLanguage.Name == JapaneseName;
                isCurrentLanguageChinese = InputLanguageManager.Current.CurrentInputLanguage.Name.StartsWith(Chinese);
                this.UpdateImeState();
            }

            private void OnGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
            {
                this.UpdateImeState();
            }

            protected override void OnTextInputStart(object sender, TextCompositionEventArgs e)
            {
                this.UpdateImeState();

                base.OnTextInputStart(sender, e);
            }

            protected override void OnTextInput(TextCompositionEventArgs e)
            {
                if (this.InputState == InputStates.Standard)
                {
                    base.OnTextInput(e);
                }
                else
                {
                    if (this.LastInputEvent == InputEvents.OnTextInputUpdate)
                    {
                        this.ClearText();
                    }

                    this.ShouldPersist = true;

                    if (!string.IsNullOrEmpty(e.Text))
                    {
                        this.OnTextInserted(this, new TextInsertedEventArgs(e.Text, this.ShouldPersist, this.ShouldStartNewComposition));
                    }

                    this.ShouldPersist = false;
                    this.ShouldStartNewComposition = false;

                    this.LastInputEvent = InputEvents.OnTextInput;
                    Type t = typeof(Caret);
                    var field = t.GetField("lastCompositionOffset", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
                    field.SetValue(this, 0);

                    // Added this, because the Caret is not correctly positioned otherwise.
                    this.Padding = new Thickness(-3, 0, 0, 0);
                }
            }


        }

  7. Brian Seekford
    Brian Seekford avatar
    12 posts
    Member since:
    Jun 2009

    Posted 28 Jul 2015 in reply to Todor Link to this post

    It turns out there is another bug related to this issue.

     If you type into the TextBox using an IME, and then click on the text being typed before it is inserted, it crashes.

    Managed Debugging Assistant 'FatalExecutionEngineError' has detected a problem in XXX
    Additional information: The runtime has encountered a fatal error. The address of the error was at 0x62467c6d, on thread 0x6b64. The error code is 0x80131623. This error may be a bug in the CLR or in the unsafe or non-verifiable portions of user code. Common sources of this bug include user marshaling errors for COM-interop or PInvoke, which may corrupt the stack.

    Steps:

    1) Set keyboard language to Japanese with Hirigana as input

    2) Type nihonngo into editor.

    3) click on the text you typed.

    4) Watch crash and say "BAHHH" I can't catch this type of exception.

    Any ideas or will this require you to fix internally?(Guessing the latter)

     

     

     

     

     

  8. Todor
    Admin
    Todor avatar
    168 posts

    Posted 30 Jul 2015 Link to this post

    Hi Brian,

    Indeed, I was able to reproduce the lastly described issue.

    I can conclude the issue is WindowsForms specific and it occurs when the UIElement.Focus() method is invoked. However, the Caret class inherits UIElement and you could change its Focusable property. As a workaround, in the Caret.OnTextInput() event handler, you could set the Caret's Focusable property to false right before the OnTextInserted invoking and then set back its value to true after the mentioned method execution. Here is a sample example code snippet of the described approach:
    protected override void OnTextInput(TextCompositionEventArgs e)
    {
          ...
            if (!string.IsNullOrEmpty(e.Text))
            {
                this.Focusable = false;
                this.OnTextInserted(this, new TextInsertedEventArgs(e.Text, this.ShouldPersist, this.ShouldStartNewComposition));
                this.Focusable = true;
            }
          ...
    }

    I hope this helps.


    Regards,
    Todor
    Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  9. Janos
    Janos avatar
    2 posts
    Member since:
    Dec 2011

    Posted 16 Nov Link to this post

    Hi all,

    I know it is relatively old topic, however we also need a workaround like this in our product, and I have to say thanks who are in this topic for samples and descriptions.

    However I would like to warn others who are thinking on to use a MyCaret implementation from the provided example, that it causes a memory leak, because every MyCaret instance subscribes to a static event (and never unsubscribes from it).

    I suggest something like this:

    public MyCaret()
    {
        Loaded += MyCaret_Loaded;
        Unloaded += MyCaret_Unloaded;
        this.GotKeyboardFocus += this.OnGotKeyboardFocus;
     
        this.isCurrentLanguageJapanese = InputLanguageManager.Current.CurrentInputLanguage.Name == JapaneseName;
    }
     
    void MyCaret_Loaded(object sender, RoutedEventArgs e)
    {
        InputLanguageManager.Current.InputLanguageChanged += this.Current_InputLanguageChanged;
    }
    void MyCaret_Unloaded(object sender, RoutedEventArgs e)
    {
        InputLanguageManager.Current.InputLanguageChanged -= this.Current_InputLanguageChanged;
    }

     

    Best Regards,

    Janos

     

  10. Brian Seekford
    Brian Seekford avatar
    12 posts
    Member since:
    Jun 2009

    Posted 16 Nov in reply to Janos Link to this post

    Yeah, I found that later.  Never posted an update .

    simple fix was to use weakeventmanager to bind the events up. 

  11. Boby
    Admin
    Boby avatar
    595 posts

    Posted 17 Nov Link to this post

    Hello all and thanks for the updates.

    I just want to add that the latest LIBs of the product contains fix for the following issue: RichTextBox: FatalExecutionEngineError is thrown when clicking in RadRichTextBox while using Microsoft Pinyin IME in Flow layout mode, which may be the one that Brian mentioned is experiencing. The first official release to contain the fix will be 2017 R1, expected in January.


    Regards,
    Boby
    Telerik by Progress
    Telerik UI for WPF is ready for Visual Studio 2017 RC! Learn more.
Back to Top
UI for WPF is Visual Studio 2017 Ready