// ********************************* // Message from Original Author: // // 2008 Jose Menendez Poo // Please give me credit if you use this code. It's all I ask. // Contact me for more info: menendezpoo@gmail.com // ********************************* // // Original project from http://ribbon.codeplex.com/ // Continue to support and maintain by http://officeribbon.codeplex.com/ using System.ComponentModel; using System.Drawing; namespace System.Windows.Forms { public class RibbonTextBox : RibbonItem { #region Fields private const int spacing = 3; internal TextBox _actualTextBox; internal bool _removingTxt; internal bool _labelVisible; internal bool _imageVisible; internal Rectangle _labelBounds; internal Rectangle _imageBounds; internal int _textboxWidth; internal int _labelWidth; internal Rectangle _textBoxBounds; internal string _textBoxText; internal bool _AllowTextEdit = true; /// /// Set to true when using a Combobox to inhibit mouse cursor from flickering as this class and Combobox /// fight for control of the cursor. /// internal bool _disableTextboxCursor; #endregion #region Events /// /// Raised when the property value has changed /// public event EventHandler TextBoxTextChanged; public event KeyPressEventHandler TextBoxKeyPress; public event KeyEventHandler TextBoxKeyDown; public event KeyEventHandler TextBoxKeyUp; public event EventHandler TextBoxValidating; public event EventHandler TextBoxValidated; #endregion #region Ctor public RibbonTextBox() { _textboxWidth = 100; _textBoxText = ""; } #endregion #region Props /// /// Gets or sets if the textbox allows editing /// [Description("Allow Test Edit")] [Category("Behavior")] [DefaultValue(true)] public bool AllowTextEdit { get => _AllowTextEdit; set { _AllowTextEdit = value; if (Canvas != null) { Canvas.Cursor = AllowTextEdit ? Cursors.IBeam : Cursors.Default; } } } // // Summary: // Gets or sets the character used to mask characters of a password in a single-line // System.Windows.Forms.TextBox control. // // Returns: // The character used to mask characters entered in a single-line System.Windows.Forms.TextBox // control. Set the value of this property to 0 (character value) if you do // not want the control to mask characters as they are typed. Equals 0 (character // value) by default. [DefaultValue('\0')] [Category("Behavior")] [Localizable(true)] [RefreshProperties(RefreshProperties.Repaint)] public char PasswordChar { get => _passwordChar; set { _passwordChar = value; if (_actualTextBox != null) { _actualTextBox.PasswordChar = value; } } } private char _passwordChar = '\0'; /// /// Gets or sets the text on the textbox /// [Category("Appearance")] [Description("Text on the textbox")] public string TextBoxText { get => _textBoxText; set { _textBoxText = value; if (_actualTextBox != null) { _actualTextBox.Text = _textBoxText; } OnTextChanged(EventArgs.Empty); } } /// /// Gets the bounds of the text on the textbox /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public virtual Rectangle TextBoxTextBounds => TextBoxBounds; /// /// Gets the bounds of the image /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public Rectangle ImageBounds => _imageBounds; /// /// Gets the bounds of the label that is shown next to the textbox /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public virtual Rectangle LabelBounds => _labelBounds; /// /// Gets a value indicating if the image is currenlty visible /// [Category("Appearance")] [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool ImageVisible => _imageVisible; /// /// Gets a value indicating if the label is currently visible /// [Category("Appearance")] [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool LabelVisible => _labelVisible; /// /// Gets the bounds of the text /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public virtual Rectangle TextBoxBounds => _textBoxBounds; /// /// Gets a value indicating if user is currently editing the text of the textbox /// [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool Editing => _actualTextBox != null; /// /// Gets or sets the width of the textbox /// [Category("Appearance")] [DefaultValue(100)] public int TextBoxWidth { get => _textboxWidth; set { _textboxWidth = value; NotifyOwnerRegionsChanged(); } } /// /// Gets or sets the width of the Label. Enter zero to auto size based on contents. /// [Category("Appearance")] [DefaultValue(0)] public int LabelWidth { get => _labelWidth; set { _labelWidth = value; NotifyOwnerRegionsChanged(); } } #endregion #region Methods /// /// Starts editing the text and focuses the TextBox /// public void StartEdit() { //if (!Enabled) return; PlaceActualTextBox(); _actualTextBox.SelectAll(); _actualTextBox.Focus(); } /// /// Ends the editing of the textbox /// public void EndEdit() { RemoveActualTextBox(); } /// /// Places the Actual TextBox on the owner so user can edit the text /// protected void PlaceActualTextBox() { _actualTextBox = new TextBox(); InitTextBox(_actualTextBox); _actualTextBox.TextChanged += _actualTextbox_TextChanged; _actualTextBox.KeyDown += _actualTextbox_KeyDown; _actualTextBox.KeyUp += _actualTextbox_KeyUp; _actualTextBox.KeyPress += _actualTextbox_KeyPress; _actualTextBox.LostFocus += _actualTextbox_LostFocus; _actualTextBox.VisibleChanged += _actualTextBox_VisibleChanged; _actualTextBox.Validating += _actualTextbox_Validating; _actualTextBox.Validated += _actualTextbox_Validated; _actualTextBox.PasswordChar = PasswordChar; _actualTextBox.Visible = true; //_actualTextBox.AcceptsTab = true; Canvas.Controls.Add(_actualTextBox); Owner.ActiveTextBox = this; } public void _actualTextBox_VisibleChanged(object sender, EventArgs e) { if (!(sender as TextBox).Visible && !_removingTxt) { RemoveActualTextBox(); } } /// /// Removes the actual TextBox that edits the text /// protected void RemoveActualTextBox() { if (_actualTextBox == null || _removingTxt) { return; } _removingTxt = true; TextBoxText = _actualTextBox.Text; _actualTextBox.Visible = false; if (_actualTextBox.Parent != null) { _actualTextBox.Parent.Controls.Remove(_actualTextBox); } _actualTextBox.Dispose(); _actualTextBox = null; RedrawItem(); _removingTxt = false; Owner.ActiveTextBox = null; } /// /// Initializes the texbox that edits the text /// /// protected virtual void InitTextBox(TextBox t) { t.Text = TextBoxText; t.BorderStyle = BorderStyle.None; t.Width = TextBoxBounds.Width - 2; t.Location = new Point( TextBoxBounds.Left + 2, Bounds.Top + (Bounds.Height - t.Height) / 2); } /// /// Handles the LostFocus event of the actual TextBox /// /// /// public void _actualTextbox_LostFocus(object sender, EventArgs e) { RemoveActualTextBox(); } /// /// Handles the KeyDown event of the actual TextBox /// /// /// public void _actualTextbox_KeyDown(object sender, KeyEventArgs e) { if (TextBoxKeyDown != null) { TextBoxKeyDown(this, e); } if (e.KeyCode == Keys.Return || e.KeyCode == Keys.Enter || e.KeyCode == Keys.Escape) { RemoveActualTextBox(); } } /// /// Handles the KeyUp event of the actual TextBox /// /// /// public void _actualTextbox_KeyUp(object sender, KeyEventArgs e) { if (TextBoxKeyUp != null) { TextBoxKeyUp(this, e); } if (e.KeyCode == Keys.Return || e.KeyCode == Keys.Enter || e.KeyCode == Keys.Escape) { RemoveActualTextBox(); } } /// /// Handles the KeyPress event of the actual TextBox /// /// /// public void _actualTextbox_KeyPress(object sender, KeyPressEventArgs e) { if (!Enabled) { return; } if (TextBoxKeyPress != null) { TextBoxKeyPress(this, e); } //bool next = false; //RibbonItem nextItem = this; //foreach (var item in this.OwnerPanel.GetItems()) //{ // if (item == this) // { // next = true; // } // else if (next) // { // nextItem = item; // break; // } //} //if (nextItem == this) //{ // var nextTab = this.OwnerPanel.OwnerTab; // var nextFoundTab = false; // foreach (var tab in this.OwnerPanel.OwnerTab.Owner.Tabs) // { // if (tab == this.OwnerPanel.OwnerTab) // { // nextFoundTab = true; // } // else if (nextFoundTab) // { // nextTab = tab; // break; // } // } // if (nextTab == this.OwnerPanel.OwnerTab) // { // nextTab.Owner.OrbSelected = true; // nextTab.Owner.ShowOrbDropDown(); // } // else // { // nextTab.Owner.ActiveTab = nextTab; // } //} //else //{ // nextItem.SetSelected(true); //} } /// /// Handles the Validating event of the actual TextBox /// /// /// public void _actualTextbox_Validating(object sender, CancelEventArgs e) { if (!Enabled) { return; } if (TextBoxValidating != null) { TextBoxValidating(this, e); } } /// /// Handles the Validated event of the actual TextBox /// /// /// public void _actualTextbox_Validated(object sender, EventArgs e) { if (!Enabled) { return; } if (TextBoxValidated != null) { TextBoxValidated(this, e); } } /// /// Handles the TextChanged event of the actual TextBox /// /// /// public void _actualTextbox_TextChanged(object sender, EventArgs e) { //Text = (sender as TextBox).Text; { TextBoxText = (sender as TextBox).Text; } } /// /// Measures the suposed height of the textobx /// /// public virtual int MeasureHeight() { return 16 + Owner.ItemMargin.Vertical; } public override void OnPaint(object sender, RibbonElementPaintEventArgs e) { if (Owner == null) { return; } Owner.Renderer.OnRenderRibbonItem(new RibbonItemRenderEventArgs(Owner, e.Graphics, Bounds, this)); if (ImageVisible) { Owner.Renderer.OnRenderRibbonItemImage(new RibbonItemBoundsEventArgs(Owner, e.Graphics, e.Clip, this, _imageBounds)); } using (StringFormat f = StringFormatFactory.NearCenterNoWrap(StringTrimming.None)) { Owner.Renderer.OnRenderRibbonItemText(new RibbonTextEventArgs(Owner, e.Graphics, Bounds, this, TextBoxTextBounds, TextBoxText, f)); if (LabelVisible) { f.Alignment = (StringAlignment)TextAlignment; Owner.Renderer.OnRenderRibbonItemText(new RibbonTextEventArgs(Owner, e.Graphics, Bounds, this, LabelBounds, Text, f)); } } } public override void SetBounds(Rectangle bounds) { base.SetBounds(bounds); _textBoxBounds = Rectangle.FromLTRB( bounds.Right - TextBoxWidth, bounds.Top, bounds.Right, bounds.Bottom); if (Image != null) { _imageBounds = new Rectangle( bounds.Left + Owner.ItemMargin.Left, bounds.Top + Owner.ItemMargin.Top, Image.Width, Image.Height); } else { _imageBounds = new Rectangle(bounds.Location, Size.Empty); } _labelBounds = Rectangle.FromLTRB( _imageBounds.Right + (_imageBounds.Width > 0 ? spacing : 0), bounds.Top, _textBoxBounds.Left - spacing, bounds.Bottom - Owner.ItemMargin.Bottom); if (SizeMode == RibbonElementSizeMode.Large) { _imageVisible = true; _labelVisible = true; } else if (SizeMode == RibbonElementSizeMode.Medium) { _imageVisible = true; _labelVisible = false; _labelBounds = Rectangle.Empty; } else if (SizeMode == RibbonElementSizeMode.Compact) { _imageBounds = Rectangle.Empty; _imageVisible = false; _labelBounds = Rectangle.Empty; _labelVisible = false; } } public override Size MeasureSize(object sender, RibbonElementMeasureSizeEventArgs e) { if (!Visible && !Owner.IsDesignMode()) { SetLastMeasuredSize(new Size(0, 0)); return LastMeasuredSize; } Size size = Size.Empty; int w = 0; int iwidth = Image != null ? Image.Width + spacing : 0; int lwidth = string.IsNullOrEmpty(Text) ? 0 : _labelWidth > 0 ? _labelWidth : e.Graphics.MeasureString(Text, Owner.Font).ToSize().Width + spacing; int twidth = TextBoxWidth; w += TextBoxWidth; switch (e.SizeMode) { case RibbonElementSizeMode.Large: w += iwidth + lwidth; break; case RibbonElementSizeMode.Medium: w += iwidth; break; } SetLastMeasuredSize(new Size(w, MeasureHeight())); return LastMeasuredSize; } public override void OnMouseEnter(MouseEventArgs e) { if (!Enabled) { return; } base.OnMouseEnter(e); if (TextBoxBounds.Contains(e.Location)) { Canvas.Cursor = AllowTextEdit ? Cursors.IBeam : Cursors.Default; } } public override void OnMouseLeave(MouseEventArgs e) { if (!Enabled) { return; } base.OnMouseLeave(e); Canvas.Cursor = Cursors.Default; } public override void OnMouseDown(MouseEventArgs e) { if (!Enabled) { return; } base.OnMouseDown(e); if (TextBoxBounds.Contains(e.X, e.Y) && _AllowTextEdit) { StartEdit(); } } public override void OnMouseMove(MouseEventArgs e) { if (!Enabled) { return; } base.OnMouseMove(e); /* Hack code. Combobox SetBound function should redefine all the bounds (refer to RibbonUpDown) of the * Combobox so that the there is no overlap between the textbox and dropdown. However for some reason * the two controls don't work the same so the position and rendering of the Combobox end up wrong. */ if (!_disableTextboxCursor) { if (TextBoxBounds.Contains(e.X, e.Y) && AllowTextEdit) { Canvas.Cursor = Cursors.IBeam; } else { Canvas.Cursor = Cursors.Default; } } } /// /// Raises the event /// /// public void OnTextChanged(EventArgs e) { if (!Enabled) { return; } NotifyOwnerRegionsChanged(); if (TextBoxTextChanged != null) { TextBoxTextChanged(this, e); } } #endregion } }