默认的TextBox只能进行一步撤消,且不存在Redo操作(二次撤消相当于一次Redo)。以下这个组件实现了TextBox的多步撤消(Undo、Redo)操作,代码改编于Kevin.SyntaxTextBox(原代码是针对RichTextBox实现的Undo、Redo功能)。 using System; using System.Collections.Generic; using System.Windows.Forms; namespace Ekinglong.Drawing.Forms { /// <summary> /// 可以执行多步撤消操作的TextBox /// </summary> public partial class TextBoxEx : TextBox { //Undo/Redo members private List<UndoRedoInfo> mUndoList = new List<UndoRedoInfo>(); private Stack<UndoRedoInfo> mRedoStack = new Stack<UndoRedoInfo>(); private bool mIsUndo = false; private UndoRedoInfo mLastInfo = new UndoRedoInfo("", 0); private int mMaxUndoRedoSteps = 50; /// <summary> /// The on text changed overrided. /// </summary> /// <param name="e"> </param> protected override void OnTextChanged(EventArgs e) { base.OnTextChanged(e); if (!mIsUndo) { mRedoStack.Clear(); mUndoList.Insert(0, mLastInfo); this.LimitUndo(); mLastInfo = new UndoRedoInfo(Text, SelectionStart); } //Invalidate(); } /// <summary> /// 设置和获取撤消操作允许的最大步数 /// </summary> public int MaxUndoRedoSteps { set { mMaxUndoRedoSteps = value; } get { return mMaxUndoRedoSteps; } } /// <summary> /// 清空Undo、Redo操作信息 /// </summary> public void ClearUndoAndRedo() { mUndoList.Clear(); mRedoStack.Clear(); } /// <summary> /// 判断是否可以进行Undo操作 /// </summary> public new bool CanUndo { get { return mUndoList.Count > 0; } } /// <summary> /// 判断是否可以进行Redo操作 /// </summary> public bool CanRedo { get { return mRedoStack.Count > 0; } } /// <summary> /// 撤消操作 /// </summary> public new void Undo() { if (!CanUndo) return; mIsUndo = true; mRedoStack.Push(new UndoRedoInfo(Text, SelectionStart)); UndoRedoInfo info = (UndoRedoInfo) mUndoList[0]; mUndoList.RemoveAt(0); Text = info.Text; SelectionStart = info.CursorLocation; ScrollToCaret(); mLastInfo = info; mIsUndo = false; } /// <summary> /// 重复操作 /// </summary> public void Redo() { if (!CanRedo) return; mIsUndo = true; mUndoList.Insert(0, new UndoRedoInfo(Text, SelectionStart)); LimitUndo(); UndoRedoInfo info = (UndoRedoInfo) mRedoStack.Pop(); Text = info.Text; SelectionStart = info.CursorLocation; ScrollToCaret(); mIsUndo = false; } private void LimitUndo() { while (mUndoList.Count > mMaxUndoRedoSteps) { mUndoList.RemoveAt(mMaxUndoRedoSteps); } } private class UndoRedoInfo { public UndoRedoInfo(string text, int cursorLoc) { Text = text; CursorLocation = cursorLoc; } public readonly int CursorLocation; public readonly string Text; } } }
http://www.chenjiliang.com/Article/View.aspx?ArticleID=19079