【问题标题】:How to get RichTextBox Undo to work better?如何让 RichTextBox Undo 更好地工作?
【发布时间】:2024-09-25 03:00:02
【问题描述】:

我正在尝试使用RichTextBox 编写文本编辑器。我现在关心的是 RichTextBox 的撤消和重做功能。

当我开始在文本框中书写时,说 1 分钟!如果我调用Undo 方法,它所做的只是我相信再次清除或重置richtextbox。我怎样才能让它工作得更好,比如撤消最后添加的单词,或者最后添加的新行……我的意思是你对撤消功能的期望。 (重做也同样重要!)

是否有属性或一些选项可以实现这一目标?还是我必须实现自己的代码?

【问题讨论】:

    标签: c# winforms richtextbox undo redo


    【解决方案1】:

    从 ahmadali 的代码继续 - 你可以把它放到一个单独的类中,并实现重做功能:

    注意。是的,每次更改文本框时它都会保存所有文本,因此如果您的应用将用于大量文本或应用将长时间打开(即几天/几周),您可以更改它

    public partial class MainForm : Form
    {
    
        Undoer undoer;
    
        public MainForm()
        {
            InitializeComponent();
    
            this.txtBox.TextChanged += new EventHandler( TextBoxTextChanged );
            this.undoer = new Undoer(ref this.txtText);
    
    
            // create a context menu
            ContextMenu menu = new ContextMenu();
            menu.MenuItems.AddRange( new MenuItem[] { 
                        new MenuItem("&Undo",  new EventHandler( this.undoer.undo_Click  )),
                        new MenuItem("&Redo",  new EventHandler( this.undoer.redo_Click  ))
            });
            this.txtBox.ContextMenu = menu;
    
            // or create keypress event 
            this.txtBox.KeyDown += new KeyEventHandler( textBox_KeyDown );
            this.KeyDown  += new KeyEventHandler( textBox_KeyDown );
        }
    
        protected void TextBoxTextChanged(object sender, EventArgs e)
        {
            undoer.Save();
        }
    
        protected void textBox_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
        {
            if (e.Modifiers == (System.Windows.Forms.Keys.Control))
            {
                if ( e.KeyCode == Keys.Z )
                {
                    this.undoer.Undo();
                    e.Handled = true;
                }
                if ( e.KeyCode == Keys.Y )
                {
                    this.undoer.Redo();
                    e.Handled = true;
                }
            }
        }
    }
    

    public class Undoer
    {
        protected System.Windows.Forms.RichTextBox txtBox;
        protected List<string> LastData = new List<string>();
        protected int  undoCount = 0;
    
        protected bool undoing   = false;
        protected bool redoing   = false;
    
    
        public Undoer(ref System.Windows.Forms.RichTextBox txtBox)
        {
            this.txtBox = txtBox;
            LastData.Add(txtBox.Text);
        }
    
        public void undo_Click(object sender, EventArgs e)
        {
            this.Undo();
        }
        public void redo_Click(object sender, EventArgs e)
        {
            this.Redo();
        }
    
        public void Undo()
        {
            try
            {
                undoing = true;
                ++undoCount;
                txtBox.Text = LastData[LastData.Count - undoCount - 1];
            }
            catch { }
            finally{ this.undoing = false; }
        }
        public void Redo()
        {
            try
            {
                if (undoCount == 0)
                    return;
    
                redoing = true;
                --undoCount;
                txtBox.Text = LastData[LastData.Count - undoCount - 1];
            }
            catch { }
            finally{ this.redoing = false; }
        }
    
        public void Save()
        {
            if (undoing || redoing)
                return;
    
            if (LastData[LastData.Count - 1] == txtBox.Text)
                return;
    
            LastData.Add(txtBox.Text);
            undoCount = 0;
        }
    }
    

    【讨论】:

      【解决方案2】:

      您可以保存最新的数据,当您想要撤消时,您可以将现在的数据更改为最后的数据!最新数据可以随时设置!

      我用一个richTextBox和一个按钮制作一个winForm,该按钮撤消写入的文本:

      using System;
      using System.Collections.Generic;
      using System.ComponentModel;
      using System.Data;
      using System.Drawing;
      using System.Linq;
      using System.Text;
      using System.Windows.Forms;
      
      namespace test
      {
      
      
      public partial class Form1 : Form
      {
          List<string> LastData = new List<string>();
      
          int undoCount = 0;
      
          public Form1()
          {
              InitializeComponent();
          }
      
          private void Form1_Load(object sender, EventArgs e)
          {
              LastData.Add(richTextBox1.Text);
          }
      
          private void button1_Click(object sender, EventArgs e)
          {
              try
              {
                  richTextBox1.Text = LastData[LastData.Count - undoCount - 1];
                  ++undoCount;
              }
              catch { }
          }
      
          private void richTextBox1_KeyPress(object sender, KeyPressEventArgs e)
          {
              LastData.Add(richTextBox1.Text);
              undoCount = 0;
          }
      }
      }
      

      但我没有找到更好的组织方式,你可以改变

      LastData.Add(richTextBox1.Text);
      undoCount = 0;
      

      保存生词或换行

      更新: 如果您想保存 Ram,您可以在多次撤消保存后删除列表中的第一个数据。

      【讨论】:

      • 我没明白,你能给出一些代码示例吗?我要问的是如何在我的应用程序处于活动状态并且用户更改文本时获得撤消点。
      • 谢谢,但是……这是一个棘手的工作!如果用户处理大量文本,您不认为这个列表会变得非常大吗?如果这是唯一的方法,那么添加一个计时器并每隔一段时间保存一次内容也是个好主意。
      • @Sean87:它用于多次撤消(而不仅仅是一次),但如果您只想撤消一次,您可以使用字符串而不使用列表作为 lastdata!