# HG changeset patch # User Ivo Smits # Date 1396646493 -7200 # Node ID ac0a29c05d03f2f226bf9ef3a485050f5c9c25dd # Parent 3347e1758e559ae732ac685f521121a43a150179 FBGUI: Improved TextBox mouse interaction diff -r 3347e1758e55 -r ac0a29c05d03 FBGUI/FBGUI.cs --- a/FBGUI/FBGUI.cs Thu Apr 03 14:42:15 2014 +0200 +++ b/FBGUI/FBGUI.cs Fri Apr 04 23:21:33 2014 +0200 @@ -658,6 +658,7 @@ public static readonly FBGCursor SizeBottomLeft = SizeTopLeft.RotateFlip(RotateFlipType.RotateNoneFlipY); public static readonly FBGCursor SizeBottomRight = SizeTopLeft.RotateFlip(RotateFlipType.RotateNoneFlipXY); public static readonly FBGCursor Hand = LoadFromResource("cursor_hand", 5, 0); + public static readonly FBGCursor IBeam = LoadFromResource("cursor_ibeam", 3, 7); public static FBGCursor ArrowCursor { get { return Arrow; } } } public class FBGRenderer : FBGContainerControl, IDisposable { @@ -1149,14 +1150,16 @@ public FBGTextBox(IFBGContainerControl parent) : base(parent) { BackColor = Color.White; Size = new Size(200, 20); + Cursor = FBGCursor.IBeam; } private String text = String.Empty; private Char passwordChar = (Char)0; private Font font = new Font(FontFamily.GenericMonospace, 10); private Brush brush = SystemBrushes.ControlText; private Boolean hasKeyboardFocus = false; - public String Text { get { return text; } set { text = value; if (CaretPosition > text.Length) CaretPosition = text.Length; Invalidate(); RaiseEvent(TextChanged); } } - public Font Font { get { return font; } set { font = value; Invalidate(); } } + private float[] characterPositions = null; + public String Text { get { return text; } set { text = value; if (CaretPosition > text.Length) CaretPosition = text.Length; characterPositions = null; Invalidate(); RaiseEvent(TextChanged); } } + public Font Font { get { return font; } set { font = value; characterPositions = null; Invalidate(); } } public Brush Brush { get { return brush; } set { brush = value; Invalidate(); } } public Color Color { set { Brush = new SolidBrush(value); } } public Int32 CaretPosition { get; private set; } @@ -1166,6 +1169,10 @@ protected override void Paint(Graphics g) { base.Paint(g); g.DrawRectangle(Pens.Gray, 0, 0, Bounds.Width - 1, Bounds.Height - 1); + float[] positions = characterPositions; + String textbuffer = text; + int textlength = textbuffer == null ? 0 : textbuffer.Length; + if (positions == null || positions.Length != textlength) characterPositions = positions = new float[text.Length]; using (StringFormat sf_nonprinting = new StringFormat(StringFormat.GenericTypographic)) { sf_nonprinting.Trimming = StringTrimming.None; sf_nonprinting.FormatFlags = StringFormatFlags.DisplayFormatControl | StringFormatFlags.MeasureTrailingSpaces; @@ -1173,43 +1180,28 @@ float x = 1; float y = 1; - float w = Width - 2; - if (hasKeyboardFocus && CaretPosition == 0) { - g.DrawLine(Pens.Black, x + 2, 2, x + 2, Height - 4); - } + if (hasKeyboardFocus && CaretPosition == 0) g.DrawLine(Pens.Black, x + 2, 2, x + 2, Height - 4); String c = passwordChar == 0 ? null : new String(passwordChar, 1); - for (int i = 0; i < text.Length; i++) { - if (passwordChar == 0) c = text.Substring(i, 1); - SizeF s = g.MeasureString(c, font, (int)Math.Ceiling(w), sf_nonprinting); + for (int i = 0; i < textlength; i++) { + if (passwordChar == 0) c = textbuffer.Substring(i, 1); g.DrawString(c, font, brush, x, y); + SizeF s = g.MeasureString(c, font, int.MaxValue, sf_nonprinting); x += (float)Math.Ceiling(s.Width); - w -= (float)Math.Ceiling(s.Width); + if (positions.Length > i) positions[i] = x; - if (hasKeyboardFocus && i == CaretPosition - 1) { - g.DrawLine(Pens.Black, x + 2, 2, x + 2, Height - 4); - } + if (hasKeyboardFocus && i == CaretPosition - 1) g.DrawLine(Pens.Black, x + 2, 2, x + 2, Height - 4); } } } + int GetCharacterIndexAtPosition(float x) { + float[] positions = characterPositions; + if (positions == null) return -1; + for (int i = 0; i < positions.Length; i++) if (x < characterPositions[i]) return i; + return characterPositions.Length; + } protected override void MouseDown(Point position, MouseButtons buttons) { hasKeyboardFocus = CaptureKeyboard(true); - CaretPosition = text.Length; - float x = 1; - String c = passwordChar == 0 ? null : new String(passwordChar, 1); - for (int i = 0; i < text.Length; i++) { - if (passwordChar == 0) c = text.Substring(i, 1); - Size s; - try { - s = TextRenderer.MeasureText(c, font, Size.Empty, TextFormatFlags.NoPadding | TextFormatFlags.NoPrefix); - } catch (Exception) { - break; - } - x += s.Width; - if (position.X < x) { - CaretPosition = i; - break; - } - } + CaretPosition = GetCharacterIndexAtPosition(position.X); Invalidate(); } protected override void KeyDown(Keys key) { @@ -1255,6 +1247,7 @@ } public void Focus() { hasKeyboardFocus = CaptureKeyboard(true); + Invalidate(); } protected override void LostKeyboardCapture() { base.LostKeyboardCapture(); diff -r 3347e1758e55 -r ac0a29c05d03 FBGUI/cursor_ibeam.png Binary file FBGUI/cursor_ibeam.png has changed diff -r 3347e1758e55 -r ac0a29c05d03 UCIS.Core.csproj --- a/UCIS.Core.csproj Thu Apr 03 14:42:15 2014 +0200 +++ b/UCIS.Core.csproj Fri Apr 04 23:21:33 2014 +0200 @@ -194,6 +194,9 @@ + + +