C# 如何在TextBox中实现自定义撤消
我想为文本框手动实现一个基本的撤销系统(因为中提到的问题)。我已经试了好几个小时了,但是我找不到办法。有人知道这是否可能吗 例如,这样做似乎需要检测到用户改变了插入符号的位置,但我不知道如何做到这一点。当然,我可以听到箭头键,并检测鼠标点击,但似乎不可能——至少在箭头键的情况下——真正说出SelectionStart是否已更改 如果有人有任何想法,我将不胜感激C# 如何在TextBox中实现自定义撤消,c#,.net,winforms,C#,.net,Winforms,我想为文本框手动实现一个基本的撤销系统(因为中提到的问题)。我已经试了好几个小时了,但是我找不到办法。有人知道这是否可能吗 例如,这样做似乎需要检测到用户改变了插入符号的位置,但我不知道如何做到这一点。当然,我可以听到箭头键,并检测鼠标点击,但似乎不可能——至少在箭头键的情况下——真正说出SelectionStart是否已更改 如果有人有任何想法,我将不胜感激 汤姆这有点老了,但听起来和你需要的一模一样: 总而言之,在替换选项卡时,只需选择框中的所有文本并添加4个空格,然后将整个文本粘贴回框中
汤姆这有点老了,但听起来和你需要的一模一样: 总而言之,在替换选项卡时,只需选择框中的所有文本并添加4个空格,然后将整个文本粘贴回框中
这应该允许用户点击ctrl+z来撤销整个操作。现在,我不知道如果他们在做空格后继续打字会发生什么。。。我假设它将从ctrl+z组合键中全部删除。这有点旧,但听起来与您需要的完全一样: 总而言之,在替换选项卡时,只需选择框中的所有文本并添加4个空格,然后将整个文本粘贴回框中
这应该允许用户点击ctrl+z来撤销整个操作。现在,我不知道如果他们在做空格后继续打字会发生什么。。。我假设它会从ctrl+z组合键中删除。您能否处理
TextChanged
事件,并在每次更改时将文本框内容推到堆栈上,然后每次用户点击Ctrl-Z时弹出并刷新TextBox
。你能处理TextChanged
事件吗?每次它发生变化时,只需将TextBox内容推到堆栈上,然后每次用户点击Ctrl-Z时弹出并刷新TextBox
。这是我开发的解决方案,对我来说效果很好:
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;
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Windows.Forms;
命名空间INQ_adm.Forms.ControlsX
{
公共类TextBoxX:TextBox
{
私有静态int UNDO_LIMIT=0;
私有列表LastData=新列表();
私有计数=0;
私有布尔撤消=false;
公共TextBoxX()
{
初始化组件();
}
受保护的覆盖bool ProcessCmdKey(参考消息消息消息,Keys keyData)
{
if(keyData==(Keys.Control | Keys.Z))
{
撤销=真;
尝试
{
++撤消计数;
this.Text=LastData[LastData.Count-undoCount-1].Text;
this.SelectionStart=LastData[LastData.Count-undoCount-1]。位置;
这个。执行布局();
}
接住
{
--撤消计数;
}
撤销=假;
返回true;
}
if(keyData==(Keys.Control | Keys.Y))
{
撤销=真;
尝试
{
--撤消计数;
this.Text=LastData[LastData.Count-undoCount+1].Text;
this.SelectionStart=LastData[LastData.Count-undoCount+1]。位置;
这个。执行布局();
}
接住
{
++撤消计数;
}
撤销=假;
返回true;
}
返回base.ProcessCmdKey(ref msg,keyData);
}
私有void textBoxX_TextChanged(对象发送方,事件参数e)
{
如果(!撤消)
{
RemoveRange(LastData.Count-undoCount,undoCount);
添加(新项(this.Text,this.SelectionStart));
撤消计数=0;
如果(撤消限制!=0&&撤消限制+1
这是我开发的解决方案,对我来说效果很好:
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;
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Windows.Forms;
命名空间INQ_adm.Forms.ControlsX
{
公共类TextBoxX:TextBox
{
私有静态int UNDO_LIMIT=0;
私有列表LastData=新列表();
私有计数=0;
私有布尔撤消=false;
公共TextBoxX()
{
初始化组件();
}
受保护的覆盖bool ProcessCmdKey(参考消息消息消息,Keys keyData)
{
if(keyData==(Keys.Control | Keys.Z))
{
撤销=真;
尝试
{
++撤消计数;
this.Text=LastData[LastData.Count-undoCount-1].Text;
this.SelectionStart=LastData[LastData.Count-undoCount-1]。位置;
这个。执行布局();
}
接住
{
--撤消计数;
}
撤销=假;
返回true;
}
if(keyData==(Keys.Control | Keys.Y))
{
撤销=真;
尝试
{
--撤消计数;
this.Text=LastData[LastData.Count-undoCount+1].Text;