預設的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