App with Undo/Redo functionality - Must click Undo/Redo Buttons twice to work

  • Thread starter Thread starter Milwaukee Broad
  • Start date Start date
M

Milwaukee Broad

Guest
I'm writing a C# .NET WinForms app in VS 2019 Community that has Undo/Redo functionality. I handle the Undo/Redo stuff using a RichTextBox's KeyDown event handler. Problem is when I click the Undo or Redo toolstrip buttons to execute the same code, the buttons must be clicked twice to execute the code. Using Ctrl+Z to undo and Ctrl+Y to redo in the KeyDown event handler works just fine.

Here's the entire code...

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 UndoRedo_Exercise
{
public partial class frmMain : Form
{
Stack<Func<object>> undoStack = new Stack<Func<object>>();
Stack<Func<object>> redoStack = new Stack<Func<object>>();

public frmMain()
{
InitializeComponent();
rtb.KeyDown += rtb_KeyDown;
}
private void FixTheButtons()
{
if (undoStack.Count == 0)
{
tsbtnUndo.Enabled = false;
}
else
{
tsbtnUndo.Enabled = true;
}

if (redoStack.Count == 0)
{
tsbtnRedo.Enabled = false;
}
else
{
tsbtnRedo.Enabled = true;
}
}
private void rtb_KeyDown(object sender, KeyEventArgs e)
{
if (e.KeyCode == Keys.ControlKey && ModifierKeys == Keys.Control) { }
else if (e.KeyCode == Keys.Z && ModifierKeys == Keys.Control)
{
Undo();
}
else if (e.KeyCode == Keys.Y && ModifierKeys == Keys.Control)
{
Redo();
}
else
{
redoStack.Clear();
StackPush(sender, undoStack);
}
}
private void tsbtnUndo_Click(object sender, EventArgs e)
{
Undo();
}
private void Undo()
{
if (undoStack.Count > 0)
{
StackPush(rtb, redoStack);
undoStack.Pop()();
}
FixTheButtons();
}
private void tsbtnRedo_Click(object sender, EventArgs e)
{
Redo();
}
private void Redo()
{
if (redoStack.Count > 0)
{
StackPush(rtb, undoStack);
redoStack.Pop()();
}
FixTheButtons();
}
private void StackPush(object sender, Stack<Func<object>> stack)
{
RichTextBox richTextBox = (RichTextBox)sender;
var tBT = rtb.Text(rtb.Text, rtb.SelectionStart);
stack.Push(tBT);
}

private void rtb_TextChanged(object sender, EventArgs e)
{
tsbtnUndo.Enabled = true;
}
}

public static class Extensions
{
public static Func<RichTextBox> Text(this RichTextBox richTextBox, string text, int sel)
{
return () =>
{
richTextBox.Text = text;
richTextBox.SelectionStart = sel;
return richTextBox;
};
}
}
}


So how can I get the toolstrip buttons to work with just one click?

Continue reading...
 
Back
Top