Closed acinside closed 3 years ago
I also have the behavior of misplaced cursor in textbox with password property = true.
Hi,
Thanks for reporting issue. Are you using UseTallSize property = false ?
Are you able to reproduce this issue with MaterialTextBox in MaterialSkinExample ?
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
Just to complete, on my side UseTallSize = True
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 ?
Was Hangul input working with previous release ? ->No
If yes, which release were you using ? ->I am using 2.2.0 release
Hangul isn't supported yet (see #147). Feel free to contribute by doing a PR.
However a cursor misplaced bug remains.
Hi @acinside ,
Could try latest PR #195 with Hangul ?
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.
@DoubleDebug : Are you able to reproduce this behaviour with example project ?
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.
And here is the example project:
Hi @acinside ,
Could try latest PR #195 with Hangul ?
same issue
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.
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?
@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
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.
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.
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; .......
↓
@ogi-sy thank you for this solution. Can you prepare a PR ? I will review it and merge it.
@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.
@ogi-sy unfortunnately your proposal doesn't solve issue when password is set and text is set by code at startup.
@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
■the use of ControlStyles.UserPaint
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. ..........
@orapps44 This is the example I implemented with Label and TextBox https://github.com/ogi-sy/ginbow/blob/main/MaterialTextBox2.cs
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
});
}
}
}
}
@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
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.
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)