如何在TextBox中实现自定义撤消

时间:2011-07-11 21:50:39

标签: c# .net winforms

我想手动为TextBox实现一个基本的撤消系统(因为my last question中提到的问题)。我一直试图这样做几个小时,但我找不到办法。有人知道这是否可行?

看起来这样做需要,例如,检测用户已经改变了插入位置,但我无法弄清楚如何做到这一点。当然,我可以听到箭头键,并检测鼠标点击,但似乎不可能 - 至少在箭头键的情况下 - 实际上告诉SelectionStart是否已更改了

如果有人有任何想法,我会很感激。

汤姆

3 个答案:

答案 0 :(得分:3)

这是我开发的解决方案,对我来说很好用:

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

namespace INQ_adm.Forms.ControlsX
{
    public class TextBoxX : TextBox
    {
        private static int UNDO_LIMIT = 0;
        private List<Item> LastData = new List<Item>();
        private int undoCount = 0;
        private Boolean undo = false;

        public TextBoxX()
        {
            InitializeComponent();
        }

       protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (keyData == (Keys.Control | Keys.Z))
            {
                undo = true;
                try
                {
                    ++undoCount;
                    this.Text = LastData[LastData.Count - undoCount - 1].text;
                    this.SelectionStart = LastData[LastData.Count - undoCount - 1].position;
                    this.PerformLayout();
                }
                catch
                {
                    --undoCount;
                }

                undo = false;
                return true;
            }

            if (keyData == (Keys.Control | Keys.Y))
            {
                undo = true;
                try
                {
                    --undoCount;
                    this.Text = LastData[LastData.Count - undoCount + 1].text;
                    this.SelectionStart = LastData[LastData.Count - undoCount + 1].position;
                    this.PerformLayout();
                }
                catch
                {
                    ++undoCount;
                }

                undo = false;
                return true;
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }

        private void textBoxX_TextChanged(object sender, EventArgs e)
        {
            if (!undo)
            {
                LastData.RemoveRange(LastData.Count - undoCount, undoCount);
                LastData.Add(new Item(this.Text, this.SelectionStart));
                undoCount = 0;
                    if (UNDO_LIMIT != 0 && UNDO_LIMIT + 1 < LastData.Count)
                {
                    LastData.RemoveAt(0);
                }
            }
        }

        private void InitializeComponent()
        {
            this.TextChanged += new System.EventHandler(this.textBoxX_TextChanged);
        }
    }

    public class Item
    {
        public String text;
        public int position;

        public Item(String text, int position)
        {
            this.text = text;
            this.position = position;
        }
    }
}

答案 1 :(得分:2)

您可以处理TextChanged事件,每次更改时只将文本框内容推送到堆栈,然后每次用户按Ctrl-Z时弹出并刷新TextBox

答案 2 :(得分:0)

这有点旧,但听起来完全像你需要的: http://msmvps.com/blogs/peterritchie/archive/2006/09/10/Changing-TextBox-Text-as-an-Undo_2D00_able-Action.aspx

总而言之,当您更换标签时,只需选中框中的所有文字,然后将4个空格附加,然后将整个文字粘贴回框中。

这应该允许用户点击ctrl + z来撤消整个事情。现在,我不知道如果他们在做完空格后继续打字会发生什么...我认为它会全部从ctrl + z按下删除。