.Net FCL 中的 System.Windows.Forms.TextBox 是一个常用的控件,然而此控件不支持插入/改写状态的切换功能。本文介绍如何来为 System.Windows.Forms.TextBox 添加此功能。
以下是本控件的全部源代码,您可以加入一个项目中直接编译以生成该控件。
注意:本控件禁止了 Multiline 功能,还有一个小 BUG 没有处理掉。
using System; using System.ComponentModel; using System.Windows.Forms;
namespace Effortech.Library.Controls { /// <summary> /// 能够切换插入/改写状态的文本框控件 /// </summary> public class OverWritableTextBox : System.Windows.Forms.TextBox {
#region Class Variables private bool isOverWrite = false; #endregion
#region Constructors public OverWritableTextBox() { base.Multiline = false; }
#endregion
#region Overrides protected override void OnGotFocus(EventArgs e) { base.OnGotFocus(e);
this.ForceSelectOneChar(); } protected override void OnMouseUp(MouseEventArgs e) { base.OnMouseUp (e); if (e.Button == MouseButtons.Left) { this.ForceSelectOneChar(); } }
protected override void OnTextChanged(EventArgs e) { base.OnTextChanged (e);
this.ForceSelectOneChar(); }
protected override void OnKeyPress(KeyPressEventArgs e) { base.OnKeyPress (e); if ((e.KeyChar == (char)8) && this.isOverWrite ) { this.SelectionLength = 0; } }
protected override void OnReadOnlyChanged(EventArgs e) { base.OnReadOnlyChanged (e); if (this.ReadOnly) { this.isOverWrite = false; this.SelectionLength = 0; } }
protected override void OnEnabledChanged(EventArgs e) { base.OnEnabledChanged (e); if (this.Enabled == false) { this.isOverWrite = false; this.SelectionLength = 0; } }
protected override void OnKeyUp(KeyEventArgs e) { base.OnKeyUp(e);
// 此处重写 OnKeyUp 并调用 ForceSelectOneChar 方法的唯一原因: // 当组合使用 Shift/Ctrl 和移动键时,可能会使得 // this.SelectionLength 为 0,这在改写状态下是不希望出现的。 // // BUG —— // 执行以下方法的负面效果是:如果使用 Shift + 左移键,当取消了所选中的字符时, // 控件会强制选取一个字符,这就使得左移键看起来失效了。 // 但是此时用户操作只要不放开左移键,仍可继续往左移动光标。 // // 应采用 Win32 KeyBoard API 来监测 Shift/Ctrl 键的弹出事件,然后再调用以下方法才比较妥当。 // 以后再补吧。 // 如果哪位兄台有什么高见,一定要告诉我哦。 this.ForceSelectOneChar(); }
protected override void OnKeyDown(KeyEventArgs e) { base.OnKeyDown(e); switch(e.KeyCode) { case Keys.Insert: if (this.ReadOnly == false) { if ( this.isOverWrite ) { this.isOverWrite = false; } else { this.isOverWrite = true; this.ForceSelectOneChar(); } } break;
case Keys.Left: case Keys.Up: if ( this.isOverWrite && // 不对有 Shift 或 Ctrl 键按下时进行任何处理。 (Control.ModifierKeys & Keys.Shift) != Keys.Shift && (Control.ModifierKeys & Keys.Control) != Keys.Control ) { if ( this.SelectionStart > 0) { this.SelectionStart--; this.SelectionLength = 1; } e.Handled = true; } break;
case Keys.Right: case Keys.Down: if ( this.isOverWrite && // 不对有 Shift 或 Ctrl 键按下时进行任何处理。 (Control.ModifierKeys & Keys.Shift) != Keys.Shift && (Control.ModifierKeys & Keys.Control) != Keys.Control) { if ( this.SelectionStart < this.Text.Length) { this.SelectionStart = this.SelectionLength + this.SelectionStart; this.SelectionLength = 1; } e.Handled = true; } break; default: this.ForceSelectOneChar(); break; } }
#endregion
/// <summary> /// 改写状态下,若没有选取任何字符,强制必须至少选取一个字符。 /// </summary> private void ForceSelectOneChar() { if (this.isOverWrite && this.SelectionLength == 0) { this.SelectionLength = 1; // 此操作当已位于最后一个位置时无效,但并不会抛出异常。 } } /// <summary> /// 因为本控件没有处理多行方式下的改写功能,所以暂禁。 /// </summary> [Browsable(false)] public new bool Multiline { get { return base.Multiline; } set { if (value == true) throw new NotSupportedException();
base.Multiline = value; } }
/// <summary> /// 获取是否处于改写状态 /// 暂时认为没有必要提供本属性的设置(set)操作 /// </summary> public bool OverWriting { get { return this.isOverWrite; } } } }
最后向 CMIC(大象)致谢。

|