Winforms文本框 - 使用Ctrl-Backspace删除整个单词

Rhy*_*nes 30 c# textbox winforms

我有一个Winforms对话框,其中包含一个允许单行输入的TextBox.我想允许用户能够按Ctrl-Backspace删除整个单词.这不是开箱即用的TextBox的默认行为; 我得到一个矩形字符,而不是删除单词.

我已确认该ShortcutsEnabled物业已设定为True.

我确实发现我可以使用RichTextBox而不是TextBox来获取我想要的行为.这个问题是RichTextBox的外观(特别是边框)与TextBox的外观不同,我不需要或不想要标记文本的能力.

所以我的问题是如何最好地处理这种情况?我错过了TextBox上的一些属性吗?或者最好使用RichTextBox,更新外观以使其一致,并禁用文本的标记?

如果没有更好的方法,我很乐意编写处理KeyDown和KeyPress事件明确的代码,但认为值得先检查一下.

小智 26

老问题,但我偶然发现了一个不需要任何额外代码的答案.

启用文本框的自动完成功能,CTRL-Backspace应该按照您的意愿工作.

CTRL-Backspace删除插入符号左侧的整个单词似乎是自动完成处理程序的" 流氓功能 ".这就是启用自动完成功能修复此问题的原因.

来源1 | 来源2

-

您可以设置启用自动完成功能AutoCompleteMode,并AutoCompleteSource为您喜欢的任何东西(例如,SuggestRecentlyUsedList)

  • 不幸的是,仅供参考,我认为这对于多行文本框不起作用:( (6认同)

Luk*_*eSw 23

/*更新:请看下面Damir的答案,它可能是一个更好的解决方案:)*/

我会通过将Ctrl + Shift + Left和Backspace发送到TextBox来模拟Ctrl + Backspace.效果几乎相同,无需手动处理控件的文本.您可以使用以下代码实现它:

class TextBoxEx : TextBox
{
    protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        if (keyData == (Keys.Control | Keys.Back))
        {
            SendKeys.SendWait("^+{LEFT}{BACKSPACE}");
            return true;
        }
        return base.ProcessCmdKey(ref msg, keyData);
    }
}
Run Code Online (Sandbox Code Playgroud)

您还可以修改app.config文件以强制SendKey类使用更新的发送键的方法:

<configuration>
  <appSettings>
    <add key="SendKeys" value="SendInput" />
  </appSettings>
</configuration>
Run Code Online (Sandbox Code Playgroud)

  • 当我按住控件并退格时,它不能按预期工作.它首次删除完整的单词,然后逐个删除字符. (11认同)

小智 8

虽然ProcessCmdKey覆盖效果很好,但它只限于Ctrl + Backspace的一次迭代,主要是因为使用SendWait模仿击键,如果你在按Backspace时按住Ctrl键,系统似乎只能识别按下Backspace键.如果您要记录覆盖的击键,您会发现一组您从未实际按下的额外键.

另一种方法是在ProcessCmdKey覆盖中显式管理文本框的外观,而不是向系统发送更多密钥.这也可以轻松应用于Ctrl + Delete.

我已经为Ctrl + Backspace行为包含了一些常见的"停止点",并使用了switch语句而不是RegEx.他们从来没有觉得足够干净,我通常最终会错过一个角色

如果您发现我的代码有任何问题,请务必告诉我.对于仍然被这个难题迷惑的人来说,祝你好运!

public class TextBoxEx : TextBox
{
    protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        if (keyData == (Keys.Back | Keys.Control))
        {
            for (int i = this.SelectionStart - 1; i > 0; i--)
            {
                switch (Text.Substring(i, 1))
                {    //set up any stopping points you want
                    case " ":
                    case ";":
                    case ",":
                    case "/":
                    case "\\":                        
                        Text = Text.Remove(i, SelectionStart - i);
                        SelectionStart = i;
                        return true;
                    case "\n":
                        Text = Text.Remove(i - 1, SelectionStart - i);
                        SelectionStart = i;
                        return true;
                }
            }
            Clear();        //in case you never hit a stopping point, the whole textbox goes blank
            return true;
        }
        else
        {
            return base.ProcessCmdKey(ref msg, keyData);
        }
    }  
}
Run Code Online (Sandbox Code Playgroud)

  • 这是我使用的解决方案,因为接受的答案仅适用于单独按下并完全释放CTRL + BACK.但是,我使用条件块而不是切换块:if(char.IsPunctuation(Text,i)|| char.IsSeparator(Text,i)|| char.IsWhiteSpace(Text,i)){...} .这将检查所有常见的分隔符类型,如空格,句点,逗号,短划线等. (2认同)

Pat*_*ald 6

我不确定如果没有自定义KeyDown或KeyPress事件,以下代码可以正常工作:

private void textBox1_KeyDown(object sender, KeyEventArgs e)
{
    if ((e.KeyCode == Keys.Back) && e.Control)
    {
        e.SuppressKeyPress = true;
        int selStart = textBox1.SelectionStart;
        while (selStart > 0 && textBox1.Text.Substring(selStart - 1, 1) == " ")
        {
            selStart--;
        }
        int prevSpacePos = -1;
        if (selStart != 0)
        {
            prevSpacePos = textBox1.Text.LastIndexOf(' ', selStart - 1);
        }
        textBox1.Select(prevSpacePos + 1, textBox1.SelectionStart - prevSpacePos - 1);
        textBox1.SelectedText = "";
    }
}
Run Code Online (Sandbox Code Playgroud)