Frage

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.

War es hilfreich?

Lösung

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;
    }
}
}

Andere Tipps

One way to do this is use the TextChanged event to periodically store the contents of richtextbox.text in an array or list, as a stack. When you undo, "pop the stack" and copy the most recent version on the stack into richtextbox.text.

TextChange can determine whether a change should be saved onto the stack, whether a new word, line, or character.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top