I have a WinForm text editor.
I would like to be able to allow the user to undo and redo changes in the Rich Text Box, like they can in Microsoft Word.
I have spent the past week or so researching how to do this, and most results seem to be regarding graphics applications.
The standard richTextBox1.Undo(); gives disappointing results, as it undoes everything that the user has written.
Does anybody have any idea how I could implement effective undo/redo? Preferably one which undoes/redoes the action word-by-word as opposed to character-by-character.
This is a very basic idea, and I'm sure that many improvements could be made.
I would create a String Array
and incrementally store the value of the RichTextBox
(In the TextChanged
event, under your own conditions) in the array. As you store the value, increment the value of a counter, say stackcount
. When the user undoes, decrement the stackcount
and set the RichTextBox.Text = array(stackcount)
. If they redo, then increment the value of the counter and set the value again. If they undo and then change the text, then clear all values onwards.
I am sure that many other people may have better suggestions/changes for this, so please post in comments and I will update, or edit it yourself!
Example in C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace RedoUndoApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public string[] RTBRedoUndo;
public int StackCount = 0;
public int OldLength = 0;
public int ChangeToSave = 5;
public bool IsRedoUndo = false;
private void Form1_Load(object sender, EventArgs e)
{
RTBRedoUndo = new string[10000];
RTBRedoUndo[0] = "";
}
private void undo_Click(object sender, EventArgs e)
{
IsRedoUndo = true;
if (StackCount > 0 && RTBRedoUndo[StackCount - 1] != null)
{
StackCount = StackCount - 1;
richTextBox1.Text = RTBRedoUndo[StackCount];
}
}
private void redo_Click(object sender, EventArgs e)
{
IsRedoUndo = true;
if (StackCount > 0 && RTBRedoUndo[StackCount + 1] != null)
{
StackCount = StackCount + 1;
richTextBox1.Text = RTBRedoUndo[StackCount];
}
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
if (IsRedoUndo == false && richTextBox1.Text.Substring(richTextBox1.Text.Length - 1, 1) == " ")//(Math.Abs(richTextBox1.Text.Length - OldLength) >= ChangeToSave && IsRedoUndo == false)
{
StackCount = StackCount + 1;
RTBRedoUndo[StackCount] = richTextBox1.Text;
OldLength = richTextBox1.Text.Length;
}
}
private void undo_MouseUp(object sender, MouseEventArgs e)
{
IsRedoUndo = false;
}
private void redo_MouseUp(object sender, MouseEventArgs e)
{
IsRedoUndo = false;
}
}
}