Undo buffer getting cleared after handling OnKeyDown in TextBox
I am subclassing TextBox:
class Editor : TextBox
I have overridden OnKeyDown, because I want tabs to be replaced by four spaces:
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.Tab) {
SelectedText = " ";
e.SuppressKeyPress = true;
}
}
This works, but unfortunately it also clears the undo buffer. The end result is that when the user presses tab, Ctrl+Z doesn't work and 'Undo' on the right-click menu becomes disabled. The problem appears to be the "e.SuppressKeyPress = true;" part.
Does anyone have any idea of how to get around this?
For more info, I am creating a fairly simple text editor, and I'm handling not only the Tab key (as above), but also the Enter key. So I have this problem with Tab and Enter. I am aware that this problem doesn't exist with RichTextBox, but for various reasons I want to use TextBox instead.
Any help would be much appreciated, as this is a show-stopping problem in my pro开发者_如何学JAVAject.
Thanks, Tom
This isn't a result of overriding OnKeyDown
, it's that you're setting SelectedText
(any text modification will have the same effect). You can see this by commenting out your code that sets the SelectedText
while leaving everything else. Obviously you won't get a tab or four characters, but the undo buffer will be preserved.
According to this blog post, you should be able to use the Paste(string)
function rather than setting the SelectedText
property and preserve the undo buffer:
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.KeyCode == Keys.Tab)
{
Paste(" ");
e.SuppressKeyPress = true;
}
}
I've finally found the solution, which is to use the Windows API as follows:
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);
}
Here is my WinApi class:
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;
}
精彩评论