[C#]实现RichTextBox的多步撤销

[C#]实现RichTextBox的多步撤销


RichTextBox默认的Undo、Redo只能进行多个单元的撤销合并操作。以下组件实现了RichTextBox的单个单元的撤销,即可以撤销一个字符。

using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace RichTextBoxEs
{
    /// <summary>
    /// 可以执行多步撤销文本框
    /// </summary>
    public partial class RichTextBoxEs : RichTextBox
    {
        private List<UndoRedoInfo> mUndoList = new List<UndoRedoInfo>();
        private Stack<UndoRedoInfo> mRedoStack = new Stack<UndoRedoInfo>();
        private bool mlsUndo = false;
        private string oldStr = "";
        /// <summary>
        /// 文本覆盖
        /// </summary>
        /// <param name="e"></param>
        protected override void OnTextChanged(EventArgs e)
        {
            //base.OnTextChanged(e);
            if (!mlsUndo)
            {
                mRedoStack.Clear();
                mUndoList.Insert(0, new UndoRedoInfo(oldStr, SelectionStart));
                this.LiMitUndo();
            }
            oldStr = Rtf;
            //Invalidate();
        }
        /// <summary>
        /// 设置最大撤销步数
        /// </summary>
        public int MaxUndoRedSteps { get; set; } = 50;
        /// <summary>
        /// 清空Undo、Redo操作信息
        /// </summary>
        public void ClearUndoAndRedo()
        {
            mUndoList.Clear();
            mRedoStack.Clear();
        }
        /// <summary>
        /// 判断是否可执行Undo
        /// </summary>
        public new bool CanUndo
        {
            get => mUndoList.Count > 0;
        }
        /// <summary>
        /// 判断是否可以执行Redo
        /// </summary>
        public new bool CanRedo
        {
            get => mRedoStack.Count > 0;
        }
        /// <summary>
        /// 撤销
        /// </summary>
        public new void Undo()
        {
            if (!CanUndo) return;
            mlsUndo = true;
            int InitialPosition = -Text.Length;
            UndoRedoInfo Info = (UndoRedoInfo)mUndoList[0];
            mUndoList.RemoveAt(0);
            mRedoStack.Push(new UndoRedoInfo(oldStr, Info.CursorLocation));
            Rtf = Info.Rtf;
            SelectionStart = Info.CursorLocation + InitialPosition + Text.Length;
            ScrollToCaret();
            mlsUndo = false;
            Focus();
        }
        /// <summary>
        /// 重做
        /// </summary>
        public new void Redo()
        {
            if (!CanRedo) return;
            mlsUndo = true;
            UndoRedoInfo Info = (UndoRedoInfo)mRedoStack.Pop();
            mUndoList.Insert(0, new UndoRedoInfo(oldStr, Info.CursorLocation));
            LiMitUndo();
            Rtf = Info.Rtf;
            SelectionStart = Info.CursorLocation;
            ScrollToCaret();
            mlsUndo = false;
            Focus();
        }
        private void LiMitUndo()
        {
            while (mUndoList.Count > MaxUndoRedSteps)
            {
                mUndoList.RemoveAt(MaxUndoRedSteps);
            }
        }
        private class UndoRedoInfo
        {
            public readonly int CursorLocation;
            public readonly string Rtf;
            public UndoRedoInfo(string rtf, int cursorLoc)
            {
                Rtf = rtf;
                CursorLocation = cursorLoc;
            }
        }
    }
}

文章思路来源于TextBox多步撤销

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值