leocb / MaterialSkin

Theming .NET WinForms, C# or VB.Net, to Google's Material Design Principles.
MIT License
446 stars 132 forks source link

I can't input the Hangul in MaterialTextBox Control #186

Closed acinside closed 3 years ago

acinside commented 3 years ago

hi~ MaterialTextBox 테스

Normal TextBox 트테스

There is a problem Hangul input

and when you longtext in a text box the cursor is misplaced (It doesn't happen in the example app, it happens in a new project) error

TomsDev67 commented 3 years ago

I also have the behavior of misplaced cursor in textbox with password property = true.

orapps44 commented 3 years ago

Hi,

Thanks for reporting issue. Are you using UseTallSize property = false ?

Are you able to reproduce this issue with MaterialTextBox in MaterialSkinExample ?

acinside commented 3 years ago

Are you using UseTallSize property = false ? -> No

Are you able to reproduce this issue with MaterialTextBox in MaterialSkinExample ? -> Cursor issue does not occur, but i can't input the Hangul

TomsDev67 commented 3 years ago

Just to complete, on my side UseTallSize = True

orapps44 commented 3 years ago

Are you using UseTallSize property = false ? -> No

Are you able to reproduce this issue with MaterialTextBox in MaterialSkinExample ? -> Cursor issue does not occur, but i can't input the Hangul

Was Hangul input working with previous release ? If yes, which release were you using ?

acinside commented 3 years ago

Was Hangul input working with previous release ? ->No

If yes, which release were you using ? ->I am using 2.2.0 release

orapps44 commented 3 years ago

Hangul isn't supported yet (see #147). Feel free to contribute by doing a PR.

However a cursor misplaced bug remains.

orapps44 commented 3 years ago

Hi @acinside ,

Could try latest PR #195 with Hangul ?

DoubleDebug commented 3 years ago

I had the same issue, even though I was writing pure English.

I think the error has to do with setting the text of the textbox through code (e.g. materialTextBox1.Text = "example"). Whenever I did that, the cursor got messed up in the UI. However, I never had issues when the textbox was empty and I manually typed the text in the UI, if that makes sense.

orapps44 commented 3 years ago

@DoubleDebug : Are you able to reproduce this behaviour with example project ?

DoubleDebug commented 3 years ago

Unfortunately, even though it is still happening in my project, I wasn't able to reproduce it in a sample project. However I did with a password textbox and the bug persists, as @acinside pointed out.

The bug occurs whenever you start typing in the textbox, the text doesn't have to be set through code. The textbox is still functional, but the cursor is misplaced. Here's a gif of the visual bug.

visual_bug

And here is the example project:

Example.zip

acinside commented 3 years ago

Hi @acinside ,

Could try latest PR #195 with Hangul ?

same issue

orapps44 commented 3 years ago

Roboto supports Latin, Greek (partial) and Cyrillic scripts. On Android, the Noto font is used for languages not supported by Roboto, including Chinese (simplified and traditional), Japanese, Korean, Thai and Hindi.

So Hangul input doesn't work because only Roboto font is currentely supported. To use Hangul and all other languages not supported by Roboto, Noto font support is required.

Feel free to contribute.

oAllen1 commented 3 years ago

I meet the misplaced cursor bug too. I only use English font and find out the misplaced error occurs in my own project but there is no problem in the example project. The reason is the target framework version of the example project is .NET Framework 4.6.1 and my own project is .NET Framework 4.7.2. Can you adapt this MaterialSkin to new version 4.7.2?

orapps44 commented 3 years ago

@DoubleDebug , @oAllen1 , @TomsDev67

I've made a PR to fix Textbox beam cursor misplaced, it works fine on my side. Could you try it ? https://github.com/leocb/MaterialSkin/tree/orapps44-patch-1

DoubleDebug commented 3 years ago

The cursor looks fine now when you simply put a password textbox on a form and try typing inside it. But I tried setting the text property through code (e.g. materialTextBox1.Text = "Example") and it messed up the cursor again.

Don't know why this happens, seems like a very odd issue.

orapps44 commented 3 years ago

I can reproduce the behaviour (only when Password property is set to true) but I don't know how to fix that.

Soon I will release a variant of MaterialTextbox based on MaterialMultiLineTextBox2. Approach is completely different, I hope this will solved that issue.

ogi-sy commented 3 years ago

image In fact, the internal font of Richtextbox is inconsistent with the displayed font. The focus position uses the size of the internal font, so it has to be set to a single font as follows protected override void OnCreateControl() { base.OnCreateControl(); LanguageOption = RichTextBoxLanguageOptions.DualFont;    .......

image

orapps44 commented 3 years ago

@ogi-sy thank you for this solution. Can you prepare a PR ? I will review it and merge it.

ogi-sy commented 3 years ago

@orapps44 Thank you for the wonderful source code How do I PR? I looked at the demo code of MaterialTextBox, it uses "Roboto", 16 LogicalFont, and it does not display Chinese, Japanese, and Korean well. For testing, I replaced it with Japanese font in MaterialSkinManager.cs, such as: メイリオ (Meiryo). So I saw the problem of cursor misplaced. I found the font change problem of RichTextBox, and finally in the OnCreateControl method of MaterialTextBox.cs I just added the following line of code to solve the problem

LanguageOption = RichTextBoxLanguageOptions.DualFont;

Maybe inheriting TextBox is better than RichTextBox.

orapps44 commented 3 years ago

@ogi-sy unfortunnately your proposal doesn't solve issue when password is set and text is set by code at startup.

ogi-sy commented 3 years ago

@orapps44 Yes, I have also seen this problem when password is set. In any case, your code has no problems in the English environment. What's more frustrating is that when using Chinese, Japanese and other input, there is a word transformation process, which does not work because of the use of ControlStyles.UserPaint but in .Net 6 it is work!

■TextBox image

■the use of ControlStyles.UserPaint image

image

This is what I can think of now. Just like the picture below, add the native TextBox and Label to the control. When the TextBox gets the focus, the Label covers the TextBox, then displays it, moves upward, and the font gradually becomes smaller. ..........

image

ogi-sy commented 3 years ago

@orapps44 This is the example I implemented with Label and TextBox https://github.com/ogi-sy/ginbow/blob/main/MaterialTextBox2.cs

Li98k commented 3 years ago

The MaterialTextBox cannot enter Chinese characters

When you enter Chinese in this control, the Chinese input box is closed

I have changed RichTextBox to TextBox,it is OK

namespace MaterialSkin.Controls { using MaterialSkin2DotNet; using MaterialSkin2DotNet.Animations; using MaterialSkin2DotNet.Controls; using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms;

public class MaterialMultiLineTextBox2 : Control, IMaterialControl
{
    //Properties for managing the material design properties
    [Browsable(false)]
    public int Depth { get; set; }
    [Browsable(false)]
    //public MaterialSkinManager SkinManager { get { return MaterialSkinManager.Instance; } }
    public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;

    [Browsable(false)]
    public MouseState MouseState { get; set; }

    public override Color BackColor { get { return Parent == null ? SkinManager.BackgroundColor : Parent.BackColor; } }

    public override string Text { get { return baseTextBox.Text; } set { baseTextBox.Text = value; } }
    public new object Tag { get { return baseTextBox.Tag; } set { baseTextBox.Tag = value; } }

    [Category("Behavior")]
    public int MaxLength { get { return baseTextBox.MaxLength; } set { baseTextBox.MaxLength = value; } }

    [Browsable(false)]
    public string SelectedText { get { return baseTextBox.SelectedText; } set { baseTextBox.SelectedText = value; } }

    [Category("Material Skin"), DefaultValue(""), Localizable(true)]
    public string Hint
    {
        get { return baseTextBox.Hint; }
        set
        {
            baseTextBox.Hint = value;
            hasHint = !String.IsNullOrEmpty(Hint);
            Invalidate();
        }
    }
    private bool _enabled;
    public new bool Enabled
    {
        get
        {
            return _enabled;
        }
        set
        {
            _enabled = value;
            base.Enabled = true;
            if (_enabled != true)
            {
                baseTextBox.ForeColor = ColorHelper.RemoveAlpha(SkinManager.TextDisabledOrHintColor, BackColor);
                baseTextBox.ReadOnly = true;
                baseTextBox.TabStop = false;
                base.Parent.Focus();
            }
            else
            {
                baseTextBox.ForeColor = ColorHelper.RemoveAlpha(SkinManager.TextHighEmphasisColor, BackColor);
                baseTextBox.ReadOnly = ReadOnly;
                baseTextBox.TabStop = true;
            }
            this.Invalidate();
        }
    }

    private bool _readonly;
    [Category("Behavior")]
    public bool ReadOnly
    {
        get { return _readonly; }
        set
        {
            _readonly = value;
            if (_enabled == true)
            {
                baseTextBox.ReadOnly = _readonly;
            }
            this.Invalidate();
        }
    }  

    public char PasswordChar
    {
        get { return baseTextBox.PasswordChar; }
        set
        {
            baseTextBox.PasswordChar = value;
        }
    }
    private Image _leadingIcon;

    [Category("Material Skin"), Browsable(true), Localizable(false)]
    /// <summary>
    /// Gets or sets the leading Icon
    /// </summary>
    public Image LeadingIcon
    {
        get { return _leadingIcon; }
        set
        {
            _leadingIcon = value;
            UpdateRects();
            preProcessIcons();
            if (AutoSize)
            {
                Refresh();
            }
            else
            {
                Invalidate();
            }
        }
    }

    private Image _trailingIcon;

    [Category("Material Skin"), Browsable(true), Localizable(false)]
    /// <summary>
    /// Gets or sets the trailing Icon
    /// </summary>
    public Image TrailingIcon
    {
        get { return _trailingIcon; }
        set
        {
            _trailingIcon = value;
            UpdateRects();
            preProcessIcons();
            if (AutoSize)
            {
                Refresh();
            }
            else
            {
                Invalidate();
            }
        }
    }
    [Browsable(false)]
    public int SelectionStart { get { return baseTextBox.SelectionStart; } set { baseTextBox.SelectionStart = value; } }
    [Browsable(false)]
    public int SelectionLength { get { return baseTextBox.SelectionLength; } set { baseTextBox.SelectionLength = value; } }
    [Browsable(false)]
    public int TextLength { get { return baseTextBox.TextLength; } }

    public void SelectAll() { baseTextBox.SelectAll(); }
    public void Clear() { baseTextBox.Clear(); }

    public void Copy() { baseTextBox.Copy(); }

    public void Cut() { baseTextBox.Cut(); }

    [Category("Material Skin"), DefaultValue(true)]
    public bool UseAccent { get; set; }

    # region Forwarding events to baseTextBox
    public event EventHandler AcceptsTabChanged
    {
        add
        {

            baseTextBox.AcceptsTabChanged += value;
        }
        remove
        {
            baseTextBox.AcceptsTabChanged -= value;
        }
    }

    public new event EventHandler AutoSizeChanged
    {
        add
        {
            baseTextBox.AutoSizeChanged += value;
        }
        remove
        {
            baseTextBox.AutoSizeChanged -= value;
        }
    }

    public new event EventHandler BackgroundImageChanged
    {
        add
        {
            baseTextBox.BackgroundImageChanged += value;
        }
        remove
        {
            baseTextBox.BackgroundImageChanged -= value;
        }
    }

    public new event EventHandler BackgroundImageLayoutChanged
    {
        add
        {
            baseTextBox.BackgroundImageLayoutChanged += value;
        }
        remove
        {
            baseTextBox.BackgroundImageLayoutChanged -= value;
        }
    }

    public new event EventHandler BindingContextChanged
    {
        add
        {
            baseTextBox.BindingContextChanged += value;
        }
        remove
        {
            baseTextBox.BindingContextChanged -= value;
        }
    }

    public event EventHandler BorderStyleChanged
    {
        add
        {
            baseTextBox.BorderStyleChanged += value;
        }
        remove
        {
            baseTextBox.BorderStyleChanged -= value;
        }
    }

    public new event EventHandler CausesValidationChanged
    {
        add
        {
            baseTextBox.CausesValidationChanged += value;
        }
        remove
        {
            baseTextBox.CausesValidationChanged -= value;
        }
    }

    public new event UICuesEventHandler ChangeUICues
    {
        add
        {
            baseTextBox.ChangeUICues += value;
        }
        remove
        {
            baseTextBox.ChangeUICues -= value;
        }
    }

    public new event EventHandler Click
    {
        add
        {
            baseTextBox.Click += value;
        }
        remove
        {
            baseTextBox.Click -= value;
        }
    }

    public new event EventHandler ClientSizeChanged
    {
        add
        {
            baseTextBox.ClientSizeChanged += value;
        }
        remove
        {
            baseTextBox.ClientSizeChanged -= value;
        }
    }

    //public new event EventHandler ContextMenuChanged
    //{
    //    add
    //    {
    //        baseTextBox.ContextMenuChanged += value;
    //    }
    //    remove
    //    {
    //        baseTextBox.ContextMenuChanged -= value;
    //    }
    //}

    public new event EventHandler ContextMenuStripChanged
    {
        add
        {
            baseTextBox.ContextMenuStripChanged += value;
        }
        remove
        {
            baseTextBox.ContextMenuStripChanged -= value;
        }
    }

    public new event ControlEventHandler ControlAdded
    {
        add
        {
            baseTextBox.ControlAdded += value;
        }
        remove
        {
            baseTextBox.ControlAdded -= value;
        }
    }

    public new event ControlEventHandler ControlRemoved
    {
        add
        {
            baseTextBox.ControlRemoved += value;
        }
        remove
        {
            baseTextBox.ControlRemoved -= value;
        }
    }

    public new event EventHandler CursorChanged
    {
        add
        {
            baseTextBox.CursorChanged += value;
        }
        remove
        {
            baseTextBox.CursorChanged -= value;
        }
    }

    public new event EventHandler Disposed
    {
        add
        {
            baseTextBox.Disposed += value;
        }
        remove
        {
            baseTextBox.Disposed -= value;
        }
    }

    public new event EventHandler DockChanged
    {
        add
        {
            baseTextBox.DockChanged += value;
        }
        remove
        {
            baseTextBox.DockChanged -= value;
        }
    }

    public new event EventHandler DoubleClick
    {
        add
        {
            baseTextBox.DoubleClick += value;
        }
        remove
        {
            baseTextBox.DoubleClick -= value;
        }
    }

    public new event DragEventHandler DragDrop
    {
        add
        {
            baseTextBox.DragDrop += value;
        }
        remove
        {
            baseTextBox.DragDrop -= value;
        }
    }

    public new event DragEventHandler DragEnter
    {
        add
        {
            baseTextBox.DragEnter += value;
        }
        remove
        {
            baseTextBox.DragEnter -= value;
        }
    }

    public new event EventHandler DragLeave
    {
        add
        {
            baseTextBox.DragLeave += value;
        }
        remove
        {
            baseTextBox.DragLeave -= value;
        }
    }

    public new event DragEventHandler DragOver
    {
        add
        {
            baseTextBox.DragOver += value;
        }
        remove
        {
            baseTextBox.DragOver -= value;
        }
    }

    public new event EventHandler EnabledChanged
    {
        add
        {
            baseTextBox.EnabledChanged += value;
        }
        remove
        {
            baseTextBox.EnabledChanged -= value;
        }
    }

    public new event EventHandler Enter
    {
        add
        {
            baseTextBox.Enter += value;
        }
        remove
        {
            baseTextBox.Enter -= value;
        }
    }

    public new event EventHandler FontChanged
    {
        add
        {
            baseTextBox.FontChanged += value;
        }
        remove
        {
            baseTextBox.FontChanged -= value;
        }
    }

    public new event EventHandler ForeColorChanged
    {
        add
        {
            baseTextBox.ForeColorChanged += value;
        }
        remove
        {
            baseTextBox.ForeColorChanged -= value;
        }
    }

    public new event GiveFeedbackEventHandler GiveFeedback
    {
        add
        {
            baseTextBox.GiveFeedback += value;
        }
        remove
        {
            baseTextBox.GiveFeedback -= value;
        }
    }

    public new event EventHandler GotFocus
    {
        add
        {
            baseTextBox.GotFocus += value;
        }
        remove
        {
            baseTextBox.GotFocus -= value;
        }
    }

    public new event EventHandler HandleCreated
    {
        add
        {
            baseTextBox.HandleCreated += value;
        }
        remove
        {
            baseTextBox.HandleCreated -= value;
        }
    }

    public new event EventHandler HandleDestroyed
    {
        add
        {
            baseTextBox.HandleDestroyed += value;
        }
        remove
        {
            baseTextBox.HandleDestroyed -= value;
        }
    }

    public new event HelpEventHandler HelpRequested
    {
        add
        {
            baseTextBox.HelpRequested += value;
        }
        remove
        {
            baseTextBox.HelpRequested -= value;
        }
    }

    public event EventHandler HideSelectionChanged
    {
        add
        {
            baseTextBox.HideSelectionChanged += value;
        }
        remove
        {
            baseTextBox.HideSelectionChanged -= value;
        }
    }

    public new event EventHandler ImeModeChanged
    {
        add
        {
            baseTextBox.ImeModeChanged += value;
        }
        remove
        {
            baseTextBox.ImeModeChanged -= value;
        }
    }

    public new event InvalidateEventHandler Invalidated
    {
        add
        {
            baseTextBox.Invalidated += value;
        }
        remove
        {
            baseTextBox.Invalidated -= value;
        }
    }

    public new event KeyEventHandler KeyDown
    {
        add
        {
            baseTextBox.KeyDown += value;
        }
        remove
        {
            baseTextBox.KeyDown -= value;
        }
    }

    public new event KeyPressEventHandler KeyPress
    {
        add
        {
            baseTextBox.KeyPress += value;
        }
        remove
        {
            baseTextBox.KeyPress -= value;
        }
    }

    public new event KeyEventHandler KeyUp
    {
        add
        {
            baseTextBox.KeyUp += value;
        }
        remove
        {
            baseTextBox.KeyUp -= value;
        }
    }

    public new event LayoutEventHandler Layout
    {
        add
        {
            baseTextBox.Layout += value;
        }
        remove
        {
            baseTextBox.Layout -= value;
        }
    }

    public new event EventHandler Leave
    {
        add
        {
            baseTextBox.Leave += value;
        }
        remove
        {
            baseTextBox.Leave -= value;
        }
    }

    public new event EventHandler LocationChanged
    {
        add
        {
            baseTextBox.LocationChanged += value;
        }
        remove
        {
            baseTextBox.LocationChanged -= value;
        }
    }

    public new event EventHandler LostFocus
    {
        add
        {
            baseTextBox.LostFocus += value;
        }
        remove
        {
            baseTextBox.LostFocus -= value;
        }
    }

    public new event EventHandler MarginChanged
    {
        add
        {
            baseTextBox.MarginChanged += value;
        }
        remove
        {
            baseTextBox.MarginChanged -= value;
        }
    }

    public event EventHandler ModifiedChanged
    {
        add
        {
            baseTextBox.ModifiedChanged += value;
        }
        remove
        {
            baseTextBox.ModifiedChanged -= value;
        }
    }

    public new event EventHandler MouseCaptureChanged
    {
        add
        {
            baseTextBox.MouseCaptureChanged += value;
        }
        remove
        {
            baseTextBox.MouseCaptureChanged -= value;
        }
    }

    public new event MouseEventHandler MouseClick
    {
        add
        {
            baseTextBox.MouseClick += value;
        }
        remove
        {
            baseTextBox.MouseClick -= value;
        }
    }

    public new event MouseEventHandler MouseDoubleClick
    {
        add
        {
            baseTextBox.MouseDoubleClick += value;
        }
        remove
        {
            baseTextBox.MouseDoubleClick -= value;
        }
    }

    public new event MouseEventHandler MouseDown
    {
        add
        {
            baseTextBox.MouseDown += value;
        }
        remove
        {
            baseTextBox.MouseDown -= value;
        }
    }

    public new event EventHandler MouseEnter
    {
        add
        {
            baseTextBox.MouseEnter += value;
        }
        remove
        {
            baseTextBox.MouseEnter -= value;
        }
    }

    public new event EventHandler MouseHover
    {
        add
        {
            baseTextBox.MouseHover += value;
        }
        remove
        {
            baseTextBox.MouseHover -= value;
        }
    }

    public new event EventHandler MouseLeave
    {
        add
        {
            baseTextBox.MouseLeave += value;
        }
        remove
        {
            baseTextBox.MouseLeave -= value;
        }
    }

    public new event MouseEventHandler MouseMove
    {
        add
        {
            baseTextBox.MouseMove += value;
        }
        remove
        {
            baseTextBox.MouseMove -= value;
        }
    }

    public new event MouseEventHandler MouseUp
    {
        add
        {
            baseTextBox.MouseUp += value;
        }
        remove
        {
            baseTextBox.MouseUp -= value;
        }
    }

    public new event MouseEventHandler MouseWheel
    {
        add
        {
            baseTextBox.MouseWheel += value;
        }
        remove
        {
            baseTextBox.MouseWheel -= value;
        }
    }

    public new event EventHandler Move
    {
        add
        {
            baseTextBox.Move += value;
        }
        remove
        {
            baseTextBox.Move -= value;
        }
    }

    public event EventHandler MultilineChanged
    {
        add
        {
            baseTextBox.MultilineChanged += value;
        }
        remove
        {
            baseTextBox.MultilineChanged -= value;
        }
    }

    public new event EventHandler PaddingChanged
    {
        add
        {
            baseTextBox.PaddingChanged += value;
        }
        remove
        {
            baseTextBox.PaddingChanged -= value;
        }
    }

    public new event PaintEventHandler Paint
    {
        add
        {
            baseTextBox.Paint += value;
        }
        remove
        {
            baseTextBox.Paint -= value;
        }
    }

    public new event EventHandler ParentChanged
    {
        add
        {
            baseTextBox.ParentChanged += value;
        }
        remove
        {
            baseTextBox.ParentChanged -= value;
        }
    }

    public new event PreviewKeyDownEventHandler PreviewKeyDown
    {
        add
        {
            baseTextBox.PreviewKeyDown += value;
        }
        remove
        {
            baseTextBox.PreviewKeyDown -= value;
        }
    }

    public new event QueryAccessibilityHelpEventHandler QueryAccessibilityHelp
    {
        add
        {
            baseTextBox.QueryAccessibilityHelp += value;
        }
        remove
        {
            baseTextBox.QueryAccessibilityHelp -= value;
        }
    }

    public new event QueryContinueDragEventHandler QueryContinueDrag
    {
        add
        {
            baseTextBox.QueryContinueDrag += value;
        }
        remove
        {
            baseTextBox.QueryContinueDrag -= value;
        }
    }

    public event EventHandler ReadOnlyChanged
    {
        add
        {
            baseTextBox.ReadOnlyChanged += value;
        }
        remove
        {
            baseTextBox.ReadOnlyChanged -= value;
        }
    }

    public new event EventHandler RegionChanged
    {
        add
        {
            baseTextBox.RegionChanged += value;
        }
        remove
        {
            baseTextBox.RegionChanged -= value;
        }
    }

    public new event EventHandler Resize
    {
        add
        {
            baseTextBox.Resize += value;
        }
        remove
        {
            baseTextBox.Resize -= value;
        }
    }

    public new event EventHandler RightToLeftChanged
    {
        add
        {
            baseTextBox.RightToLeftChanged += value;
        }
        remove
        {
            baseTextBox.RightToLeftChanged -= value;
        }
    }

    public new event EventHandler SizeChanged
    {
        add
        {
            baseTextBox.SizeChanged += value;
        }
        remove
        {
            baseTextBox.SizeChanged -= value;
        }
    }

    public new event EventHandler StyleChanged
    {
        add
        {
            baseTextBox.StyleChanged += value;
        }
        remove
        {
            baseTextBox.StyleChanged -= value;
        }
    }

    public new event EventHandler SystemColorsChanged
    {
        add
        {
            baseTextBox.SystemColorsChanged += value;
        }
        remove
        {
            baseTextBox.SystemColorsChanged -= value;
        }
    }

    public new event EventHandler TabIndexChanged
    {
        add
        {
            baseTextBox.TabIndexChanged += value;
        }
        remove
        {
            baseTextBox.TabIndexChanged -= value;
        }
    }

    public new event EventHandler TabStopChanged
    {
        add
        {
            baseTextBox.TabStopChanged += value;
        }
        remove
        {
            baseTextBox.TabStopChanged -= value;
        }
    }

    public new event EventHandler TextChanged
    {
        add
        {
            baseTextBox.TextChanged += value;
        }
        remove
        {
            baseTextBox.TextChanged -= value;
        }
    }

    public new event EventHandler Validated
    {
        add
        {
            baseTextBox.Validated += value;
        }
        remove
        {
            baseTextBox.Validated -= value;
        }
    }

    public new event CancelEventHandler Validating
    {
        add
        {
            baseTextBox.Validating += value;
        }
        remove
        {
            baseTextBox.Validating -= value;
        }
    }

    public new event EventHandler VisibleChanged
    {
        add
        {
            baseTextBox.VisibleChanged += value;
        }
        remove
        {
            baseTextBox.VisibleChanged -= value;
        }
    }
    # endregion

    //private readonly AnimationManager animationManager;
    private readonly AnimationManager _animationManager;
    private Dictionary<string, TextureBrush> iconsBrushes;
    private Dictionary<string, TextureBrush> iconsErrorBrushes;
    public bool isFocused = false;
    private const int HINT_TEXT_SMALL_SIZE = 18;
    private const int HINT_TEXT_Y = 14;
    private const int HINT_TEXT_SMALL_Y = 4;
    private const int LINE_BOTTOM_PADDING = 3;
    //输入控件距离边缘的距离 
    private const int TOP_PADDING = 10;
    private const int BOTTOM_PADDING = 10;
    private   int LEFT_PADDING = 16;
    private   int RIGHT_PADDING = 12;
    private int LINE_Y;
    private bool hasHint;
    private int HEIGHT = 50;
    private Rectangle _leadingIconBounds;
    private Rectangle _trailingIconBounds;
    private Rectangle _textfieldBounds;

    private bool _UseTallSize = true;
    [Category("Material Skin"), DefaultValue(true), Description("Using a larger size enables the hint to always be visible")]
    public bool UseTallSize
    {
        get { return _UseTallSize; }
        set
        {
            _UseTallSize = value;
            Invalidate();
        }
    }
    private bool _errorState = false;
    private string _errorMsg = "";

    protected readonly BaseTextBox baseTextBox;
    public MaterialMultiLineTextBox2()
    {
        // Material Properties
        UseAccent = true;

        SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.DoubleBuffer, true);

        // Animations
        _animationManager = new AnimationManager
        {
            Increment = 0.06,
            AnimationType = AnimationType.EaseInOut,
            InterruptAnimation = false
        };
        _animationManager.OnAnimationProgress += sender => Invalidate();

        baseTextBox = new BaseTextBox
        {

            BorderStyle = BorderStyle.None,

            Font = SkinManager.getFontByType(MaterialSkinManager.fontType.Subtitle1),
            ForeColor = SkinManager.TextHighEmphasisColor,
            Multiline = true
        };

        Enabled = true;
        ReadOnly = false;
        Size = new Size(250, 100);
        UpdateRects();

        if (!Controls.Contains(baseTextBox) && !DesignMode)
        {
            Controls.Add(baseTextBox);
        }

        baseTextBox.ReadOnlyChanged += (sender, args) =>
        {
            if (_enabled)
            {
                isFocused = true;
                //Invalidate();
                _animationManager.StartNewAnimation(AnimationDirection.In);
            }
            else
            {
                isFocused = false;
                //Invalidate();
                _animationManager.StartNewAnimation(AnimationDirection.Out);
            }
        };
        baseTextBox.GotFocus += (sender, args) =>
        {
            if (_enabled)
            {
                isFocused = true;
                _animationManager.StartNewAnimation(AnimationDirection.In);
             //   baseTextBox.Location = new Point(LEFT_PADDING - HINT_TEXT_SMALL_Y, TOP_PADDING + hintTextSize);
            }
            else
                base.Focus();
        };
        baseTextBox.LostFocus += (sender, args) =>
        {
            isFocused = false;
            _animationManager.StartNewAnimation(AnimationDirection.Out);
        };
        BackColorChanged += (sender, args) =>
        {
            baseTextBox.BackColor = BackColor;
            baseTextBox.ForeColor = SkinManager.TextHighEmphasisColor;
        };

        baseTextBox.TextChanged += new EventHandler(Redraw);

        baseTextBox.TabStop = true;
        this.TabStop = false;
    }

    private void Redraw(object sencer, EventArgs e)
    {
        Invalidate();
    }
    int hintTextSize = 16;
    protected override void OnPaint(PaintEventArgs pevent)
    {
        var g = pevent.Graphics;
        g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
        g.Clear(Parent.BackColor);

        SolidBrush backBrush = new SolidBrush(DrawHelper.BlendColor(Parent.BackColor, SkinManager.BackgroundAlternativeColor, SkinManager.BackgroundAlternativeColor.A));

        g.FillRectangle(
            !_enabled ? SkinManager.BackgroundDisabledBrush : // Disabled
            isFocused ? SkinManager.BackgroundFocusBrush :  // Focused
            MouseState == MouseState.HOVER ? SkinManager.BackgroundHoverBrush : // Hover
            backBrush, // Normal
            ClientRectangle.X, ClientRectangle.Y, ClientRectangle.Width, LINE_Y);

        baseTextBox.BackColor = !_enabled ? ColorHelper.RemoveAlpha(SkinManager.BackgroundDisabledColor, BackColor) : //Disabled
                        isFocused ? DrawHelper.BlendColor(BackColor, SkinManager.BackgroundFocusColor, SkinManager.BackgroundFocusColor.A) : //Focused
                        MouseState == MouseState.HOVER ? DrawHelper.BlendColor(BackColor, SkinManager.BackgroundHoverColor, SkinManager.BackgroundHoverColor.A) : // Hover
                        DrawHelper.BlendColor(BackColor, SkinManager.BackgroundAlternativeColor, SkinManager.BackgroundAlternativeColor.A); // Normal

        // baseTextBox.BackColor = Color.Red;
        //Leading Icon
        if (LeadingIcon != null)
        {
            g.FillRectangle(iconsBrushes["_leadingIcon"], _leadingIconBounds);
        }

        //Trailing Icon
        if (TrailingIcon != null)
        {
            if (_errorState)
                g.FillRectangle(iconsErrorBrushes["_trailingIcon"], _trailingIconBounds);
            else
                g.FillRectangle(iconsBrushes["_trailingIcon"], _trailingIconBounds);
        }
        // HintText
        bool userTextPresent = !String.IsNullOrEmpty(Text);

        Rectangle hintRect = new Rectangle(LEFT_PADDING, HINT_TEXT_Y, Width - LEFT_PADDING - RIGHT_PADDING, LINE_Y);

        // bottom line base
        g.FillRectangle(SkinManager.DividersAlternativeBrush, 0, LINE_Y, Width, 1);

        // No animation
        if (hasHint   && (isFocused || userTextPresent))
        {
            // hint text
            hintRect = new Rectangle(LEFT_PADDING, HINT_TEXT_SMALL_Y, Width - LEFT_PADDING - RIGHT_PADDING, HINT_TEXT_SMALL_SIZE);
            hintTextSize = 12;
            baseTextBox.Location = new Point(LEFT_PADDING - HINT_TEXT_SMALL_Y , TOP_PADDING + hintTextSize);
            baseTextBox.Width = Width - (LEFT_PADDING + RIGHT_PADDING-10);
        }
        else
        {
            hintTextSize = 16;
        baseTextBox.Location = new Point(Width, TOP_PADDING + hintTextSize);
        }

        // bottom line
        if (isFocused)
        {
            g.FillRectangle(_errorState ? SkinManager.BackgroundHoverRedBrush : UseAccent ? SkinManager.ColorScheme.AccentBrush : SkinManager.ColorScheme.PrimaryBrush, 0, LINE_Y, Width, 2);
        }

        // g.Clip = new Region(ClientRectangle);
        // Draw hint text
        if (hasHint)
        //if (hasHint && (isFocused || !String.IsNullOrEmpty(Text)))
        {
            using (NativeTextRenderer NativeText = new NativeTextRenderer(g))
            {
                NativeText.DrawTransparentText(
                Hint+ _errorMsg,
                SkinManager.getTextBoxFontBySize(hintTextSize),
                Enabled ? !_errorState || (!userTextPresent && !isFocused) ? isFocused ? UseAccent ?
                SkinManager.ColorScheme.AccentColor : // Focus Accent
                SkinManager.ColorScheme.PrimaryColor : // Focus Primary
                SkinManager.TextMediumEmphasisColor : // not focused
                SkinManager.BackgroundHoverRedColor : // error state
                SkinManager.TextDisabledOrHintColor, // Disabled
                hintRect.Location,
                hintRect.Size,
                NativeTextRenderer.TextAlignFlags.Left );
            }
        }

    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);

        if (DesignMode)
            return;
    }
    protected override void OnMouseDown(MouseEventArgs e)
    {

        {
            if (DesignMode)
                return;
        }
        baseTextBox?.Focus();
        base.OnMouseDown(e);
    }
    protected override void OnTextChanged(EventArgs e)
    {
        base.OnTextChanged(e);
        Invalidate();
    }

    protected override void OnMouseEnter(EventArgs e)
    {
        base.OnMouseEnter(e);
        MouseState = MouseState.HOVER;
        Invalidate();
    }

    protected override void OnMouseLeave(EventArgs e)
    {
        if (this.ClientRectangle.Contains(this.PointToClient(Control.MousePosition)))
            return;
        else
        {
            base.OnMouseLeave(e);
            MouseState = MouseState.OUT;
            Invalidate();
        }
    }
    public void SetErrorState(bool ErrorState,string errMsg="")
    {
        _errorState = ErrorState;
        _errorMsg = errMsg;
        Invalidate();
    }
    protected override void OnResize(EventArgs e)
    {
        base.OnResize(e);
        baseTextBox.Height = Height - (TOP_PADDING + BOTTOM_PADDING + hintTextSize - LINE_BOTTOM_PADDING - HINT_TEXT_SMALL_Y);

        baseTextBox.Location = new Point(LEFT_PADDING - HINT_TEXT_SMALL_Y + 20, TOP_PADDING + hintTextSize);

        LINE_Y = Height - LINE_BOTTOM_PADDING;
        UpdateRects(false);
        preProcessIcons();

        baseTextBox.Width = Width - (LEFT_PADDING + RIGHT_PADDING);
    }

    protected override void OnCreateControl()
    {
        base.OnCreateControl();

        // events
        MouseState = MouseState.OUT;

    }
    #region Icon
    private const int ICON_SIZE = 24;
    private static Size ResizeIcon(Image Icon)
    {
        int newWidth, newHeight;
        //Resize icon if greater than ICON_SIZE
        if (Icon.Width > ICON_SIZE || Icon.Height > ICON_SIZE)
        {
            //calculate aspect ratio
            float aspect = Icon.Width / (float)Icon.Height;

            //calculate new dimensions based on aspect ratio
            newWidth = (int)(ICON_SIZE * aspect);
            newHeight = (int)(newWidth / aspect);

            //if one of the two dimensions exceed the box dimensions
            if (newWidth > ICON_SIZE || newHeight > ICON_SIZE)
            {
                //depending on which of the two exceeds the box dimensions set it as the box dimension and calculate the other one based on the aspect ratio
                if (newWidth > newHeight)
                {
                    newWidth = ICON_SIZE;
                    newHeight = (int)(newWidth / aspect);
                }
                else
                {
                    newHeight = ICON_SIZE;
                    newWidth = (int)(newHeight * aspect);
                }
            }
        }
        else
        {
            newWidth = Icon.Width;
            newHeight = Icon.Height;
        }

        return new Size()
        {
            Height = newHeight,
            Width = newWidth
        };
    }

    private void preProcessIcons()
    {
        if (_trailingIcon == null && _leadingIcon == null) return;

        // Calculate lightness and color
        float l = (SkinManager.Theme == MaterialSkinManager.Themes.LIGHT) ? 0f : 1f;

        // Create matrices
        float[][] matrixGray = {
                new float[] {   0,   0,   0,   0,  0}, // Red scale factor
                new float[] {   0,   0,   0,   0,  0}, // Green scale factor
                new float[] {   0,   0,   0,   0,  0}, // Blue scale factor
                new float[] {   0,   0,   0, Enabled ? .7f : .3f,  0}, // alpha scale factor
                new float[] {   l,   l,   l,   0,  1}};// offset

        float[][] matrixRed = {
                new float[] {   0,   0,   0,   0,  0}, // Red scale factor
                new float[] {   0,   0,   0,   0,  0}, // Green scale factor
                new float[] {   0,   0,   0,   0,  0}, // Blue scale factor
                new float[] {   0,   0,   0,   1,  0}, // alpha scale factor
                new float[] {   1,   0,   0,   0,  1}};// offset

        ColorMatrix colorMatrixGray = new ColorMatrix(matrixGray);
        ColorMatrix colorMatrixRed = new ColorMatrix(matrixRed);

        ImageAttributes grayImageAttributes = new ImageAttributes();
        ImageAttributes redImageAttributes = new ImageAttributes();

        // Set color matrices
        grayImageAttributes.SetColorMatrix(colorMatrixGray, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
        redImageAttributes.SetColorMatrix(colorMatrixRed, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);

        // Create brushes
        iconsBrushes = new Dictionary<string, TextureBrush>(2);
        iconsErrorBrushes = new Dictionary<string, TextureBrush>(2);

        // Image Rect
        Rectangle destRect = new Rectangle(0, 0, ICON_SIZE, ICON_SIZE);

        if (_leadingIcon != null)
        {
            // ********************
            // *** _leadingIcon ***
            // ********************

            //Resize icon if greater than ICON_SIZE
            Size newSize_leadingIcon = ResizeIcon(_leadingIcon);
            Bitmap _leadingIconIconResized = new Bitmap(_leadingIcon, newSize_leadingIcon.Width, newSize_leadingIcon.Height);

            // Create a pre-processed copy of the image (GRAY)
            Bitmap bgray = new Bitmap(destRect.Width, destRect.Height);
            using (Graphics gGray = Graphics.FromImage(bgray))
            {
                gGray.DrawImage(_leadingIconIconResized,
                    new Point[] {
                                new Point(0, 0),
                                new Point(destRect.Width, 0),
                                new Point(0, destRect.Height),
                    },
                    destRect, GraphicsUnit.Pixel, grayImageAttributes);
            }

            // added processed image to brush for drawing
            TextureBrush textureBrushGray = new TextureBrush(bgray);

            textureBrushGray.WrapMode = System.Drawing.Drawing2D.WrapMode.Clamp;

            var iconRect = _leadingIconBounds;

            textureBrushGray.TranslateTransform(iconRect.X + iconRect.Width / 2 - _leadingIconIconResized.Width / 2,
                                                iconRect.Y + iconRect.Height / 2 - _leadingIconIconResized.Height / 2);

            // add to dictionary
            iconsBrushes.Add("_leadingIcon", textureBrushGray);
        }

        if (_trailingIcon != null)
        {
            // *********************
            // *** _trailingIcon ***
            // *********************

            //Resize icon if greater than ICON_SIZE
            Size newSize_trailingIcon = ResizeIcon(_trailingIcon);
            Bitmap _trailingIconResized = new Bitmap(_trailingIcon, newSize_trailingIcon.Width, newSize_trailingIcon.Height);

            // Create a pre-processed copy of the image (GRAY)
            Bitmap bgray = new Bitmap(destRect.Width, destRect.Height);
            using (Graphics gGray = Graphics.FromImage(bgray))
            {
                gGray.DrawImage(_trailingIconResized,
                    new Point[] {
                                new Point(0, 0),
                                new Point(destRect.Width, 0),
                                new Point(0, destRect.Height),
                    },
                    destRect, GraphicsUnit.Pixel, grayImageAttributes);
            }

            //Create a pre - processed copy of the image(RED)
            Bitmap bred = new Bitmap(destRect.Width, destRect.Height);
            using (Graphics gred = Graphics.FromImage(bred))
            {
                gred.DrawImage(_trailingIconResized,
                    new Point[] {
                                new Point(0, 0),
                                new Point(destRect.Width, 0),
                                new Point(0, destRect.Height),
                    },
                    destRect, GraphicsUnit.Pixel, redImageAttributes);
            }

            // added processed image to brush for drawing
            TextureBrush textureBrushGray = new TextureBrush(bgray);
            TextureBrush textureBrushRed = new TextureBrush(bred);

            textureBrushGray.WrapMode = System.Drawing.Drawing2D.WrapMode.Clamp;
            textureBrushRed.WrapMode = System.Drawing.Drawing2D.WrapMode.Clamp;

            var iconRect = _trailingIconBounds;

            textureBrushGray.TranslateTransform(iconRect.X + iconRect.Width / 2 - _trailingIconResized.Width / 2,
                                                iconRect.Y + iconRect.Height / 2 - _trailingIconResized.Height / 2);
            textureBrushRed.TranslateTransform(iconRect.X + iconRect.Width / 2 - _trailingIconResized.Width / 2,
                                                 iconRect.Y + iconRect.Height / 2 - _trailingIconResized.Height / 2);

            // add to dictionary
            iconsBrushes.Add("_trailingIcon", textureBrushGray);
            //iconsSelectedBrushes.Add(0, textureBrushColor);
            iconsErrorBrushes.Add("_trailingIcon", textureBrushRed);
        }
    }

    private void UpdateRects(bool RedefineTextField = true)
    {
        if (LeadingIcon != null)
            LEFT_PADDING = SkinManager.FORM_PADDING + ICON_SIZE;
        else
            LEFT_PADDING = SkinManager.FORM_PADDING;

        if (_trailingIcon != null)
            RIGHT_PADDING = SkinManager.FORM_PADDING + ICON_SIZE;
        else
            RIGHT_PADDING = SkinManager.FORM_PADDING;

        _leadingIconBounds = new Rectangle(8, (HEIGHT / 2) - (ICON_SIZE / 2), ICON_SIZE, ICON_SIZE);
        _trailingIconBounds = new Rectangle(Width - (ICON_SIZE + 8), (HEIGHT / 2) - (ICON_SIZE / 2), ICON_SIZE, ICON_SIZE);
        _textfieldBounds = new Rectangle(LEFT_PADDING, ClientRectangle.Y, Width - LEFT_PADDING - RIGHT_PADDING, LINE_Y);

        //if (RedefineTextField)
        //{
        //    var rect = new Rectangle(LEFT_PADDING, UseTallSize ? hasHint ?
        //(HINT_TEXT_SMALL_Y + HINT_TEXT_SMALL_SIZE) : // Has hint and it's tall
        //(int)(LINE_Y / 3.5) : // No hint and tall
        //Height / 5, // not tall
        //ClientSize.Width - LEFT_PADDING - RIGHT_PADDING, LINE_Y);
        //    RECT rc = new RECT(rect);
        //    SendMessageRefRect(Handle, EM_SETRECT, 0, ref rc);
        //}
    }

    #endregion
    protected class BaseTextBox : TextBox, IMaterialControl
    {
        //Properties for managing the material design properties
        [Browsable(false)]
        public int Depth { get; set; }

        [Browsable(false)]
        public MaterialSkinManager SkinManager => MaterialSkinManager.Instance;

        [Browsable(false)]
        public MouseState MouseState { get; set; }

        private string hint = string.Empty;
        public string Hint
        {
            get { return hint; }
            set
            {
                hint = value;
            }
        }

        public new void SelectAll()
        {
            BeginInvoke((MethodInvoker)delegate ()
            {
                base.Focus();
                base.SelectAll();
            });
        }

        public BaseTextBox()
        {
            MaterialContextMenuStrip cms = new TextBoxContextMenuStrip();
            cms.Opening += ContextMenuStripOnOpening;
            cms.OnItemClickStart += ContextMenuStripOnItemClickStart;
            ContextMenuStrip = cms;
            this.Multiline = true;

            //this.ScrollBars = ScrollBars.Vertical;
        }

        protected override void OnGotFocus(EventArgs e)
        {
            base.OnGotFocus(e);
            Invalidate();
        }

        protected override void OnLostFocus(EventArgs e)
        {
            base.OnLostFocus(e);
            Invalidate();
        }

        private const int WM_ENABLE = 0x0A;
        private const int WM_PAINT = 0xF;
        private const UInt32 WM_USER = 0x0400;
        private const UInt32 EM_SETBKGNDCOLOR = (WM_USER + 67);
        private const UInt32 WM_KILLFOCUS = 0x0008;
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);

            if (m.Msg == WM_PAINT)
            {
                if (m.Msg == WM_ENABLE)
                {
                    Graphics g = Graphics.FromHwnd(Handle);
                    Rectangle bounds = new Rectangle(0, 0, Width, Height);
                    g.FillRectangle(SkinManager.BackgroundDisabledBrush, bounds);
                }
            }

            //if (m.Msg == WM_PAINT && String.IsNullOrEmpty(Text) && !Focused)
            //{
                //using (NativeTextRenderer NativeText = new NativeTextRenderer(Graphics.FromHwnd(m.HWnd)))
                //{
                //    int hintTextSize = 16;
                //    NativeText.DrawTransparentText(
                //    Hint,
                //    //   SkinManager.getTextBoxFontBySize(hintTextSize),//
                //    SkinManager.getFontByType(MaterialSkinManager.fontType.Subtitle1),
                //    !this.ReadOnly ?
                //    ColorHelper.RemoveAlpha(SkinManager.TextMediumEmphasisColor, BackColor) : // not focused
                //    ColorHelper.RemoveAlpha(SkinManager.TextDisabledOrHintColor, BackColor), // Disabled
                //   new Point(4, -12), //ClientRectangle.Size.Height>70? ClientRectangle.Location:new Point(ClientRectangle.Location.X+4, ClientRectangle.Location.Y-12),
                //    ClientRectangle.Size,
                //    NativeTextRenderer.TextAlignFlags.Left | NativeTextRenderer.TextAlignFlags.Top);

                //}
            //}

            if (m.Msg == EM_SETBKGNDCOLOR)
            {
                Invalidate();
            }

            if (m.Msg == WM_KILLFOCUS) //set border back to normal on lost focus
            {
                Invalidate();
            }

        }

        private void ContextMenuStripOnItemClickStart(object sender, ToolStripItemClickedEventArgs toolStripItemClickedEventArgs)
        {
            switch (toolStripItemClickedEventArgs.ClickedItem.Text)
            {
                case "Undo":
                    Undo();
                    break;
                case "Cut":
                    Cut();
                    break;
                case "Copy":
                    Copy();
                    break;
                case "Paste":
                    Paste();
                    break;
                case "Delete":
                    SelectedText = string.Empty;
                    break;
                case "Select All":
                    SelectAll();
                    break;
            }
        }

        private void ContextMenuStripOnOpening(object sender, CancelEventArgs cancelEventArgs)
        {
            var strip = sender as TextBoxContextMenuStrip;
            if (strip != null)
            {
                strip.undo.Enabled = CanUndo;
                strip.cut.Enabled = !string.IsNullOrEmpty(SelectedText);
                strip.copy.Enabled = !string.IsNullOrEmpty(SelectedText);
                strip.paste.Enabled = Clipboard.ContainsText();
                strip.delete.Enabled = !string.IsNullOrEmpty(SelectedText);
                strip.selectAll.Enabled = !string.IsNullOrEmpty(Text);
            }
        }

    }

    private class TextBoxContextMenuStrip : MaterialContextMenuStrip
    {
        public readonly ToolStripItem undo = new MaterialToolStripMenuItem { Text = "Undo" };
        public readonly ToolStripItem seperator1 = new ToolStripSeparator();
        public readonly ToolStripItem cut = new MaterialToolStripMenuItem { Text = "Cut" };
        public readonly ToolStripItem copy = new MaterialToolStripMenuItem { Text = "Copy" };
        public readonly ToolStripItem paste = new MaterialToolStripMenuItem { Text = "Paste" };
        public readonly ToolStripItem delete = new MaterialToolStripMenuItem { Text = "Delete" };
        public readonly ToolStripItem seperator2 = new ToolStripSeparator();
        public readonly ToolStripItem selectAll = new MaterialToolStripMenuItem { Text = "Select All" };

        public TextBoxContextMenuStrip()
        {
            Items.AddRange(new[]
            {
                undo,
                seperator1,
                cut,
                copy,
                paste,
                delete,
                seperator2,
                selectAll
            });
        }
    }
}

}

Quekie commented 2 years ago

@orapps44 Thank you for the wonderful source code How do I PR? I looked at the demo code of MaterialTextBox, it uses "Roboto", 16 LogicalFont, and it does not display Chinese, Japanese, and Korean well. For testing, I replaced it with Japanese font in MaterialSkinManager.cs, such as: メイリオ (Meiryo). So I saw the problem of cursor misplaced. I found the font change problem of RichTextBox, and finally in the OnCreateControl method of MaterialTextBox.cs I just added the following line of code to solve the problem

LanguageOption = RichTextBoxLanguageOptions.DualFont;

Maybe inheriting TextBox is better than RichTextBox. @orapps44 Hey I fond a input method sougou which can input chinese , i don't know how it works ,maybe it can be a workaround

orapps44 commented 2 years ago

Hey,

Use MaterialTextBox2 control instead of MaterialTextBox.

As allready mentioned :

Roboto supports Latin, Greek (partial) and Cyrillic scripts. On Android, the Noto font is used for languages not supported by Roboto, including Chinese (simplified and traditional), Japanese, Korean, Thai and Hindi.

A good improvement would be to add support of Noto font.