撤消缓冲区清除后处理OnKeyDown在文本框

本文关键字:文本 OnKeyDown 后处理 缓冲区 清除 撤消 | 更新日期: 2023-09-27 18:01:41

我正在子类化TextBox:

class Editor : TextBox

我已经重写了OnKeyDown,因为我想用四个空格替换制表符:

protected override void OnKeyDown(KeyEventArgs e)
{
    if (e.KeyCode == Keys.Tab) {
        SelectedText = "    ";
        e.SuppressKeyPress = true;
    }
}

这是可行的,但不幸的是它也会清除undo缓冲区。最终的结果是,当用户按tab键时,Ctrl+Z不起作用,右键菜单上的"撤消"功能被禁用。问题似乎是"e.p suppresskeypress = true;"部分。

有谁知道如何解决这个问题吗?

更多信息,我正在创建一个相当简单的文本编辑器,我不仅处理Tab键(如上所述),而且还处理Enter键。我在按Tab键和回车键时遇到了这个问题。我知道这个问题不存在与RichTextBox,但出于各种原因,我想使用TextBox代替。

任何帮助都将非常感激,因为这是我项目中一个引人注目的问题。

谢谢,汤姆

撤消缓冲区清除后处理OnKeyDown在文本框

这不是重写OnKeyDown的结果,而是您设置了SelectedText(任何文本修改都会产生相同的效果)。您可以通过注释掉设置SelectedText而留下其他所有内容的代码来看到这一点。显然,你不会得到一个制表符或四个字符,但撤销缓冲区将被保留。

根据这篇博客文章,你应该能够使用Paste(string)函数,而不是设置SelectedText属性,并保留撤消缓冲区:

protected override void OnKeyDown(KeyEventArgs e)
{
    if (e.KeyCode == Keys.Tab) 
    {
        Paste("    ");
        e.SuppressKeyPress = true;
    }
}

我终于找到了解决方案,这是使用Windows API如下:

protected override void OnKeyDown(KeyEventArgs e)
{
    if (e.KeyCode == Keys.Tab) {
        WinApi.SendMessage(Handle, WinApi.WmChar, WinApi.VkSpace, (IntPtr)4);
        e.SuppressKeyPress = true;
    }
    base.OnKeyDown(e);
}
这是我的WinApi类:
using System;
using System.Runtime.InteropServices;
class WinApi
{ 
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
    public const           UInt32 WmChar  =         0x102;
    public static readonly IntPtr VkSpace = (IntPtr)0x20;
}