我该如何在WinForm的TextBox中允许Ctrl+A?

62

我正在提出一个已经在这里提问(甚至已经回答)的问题: 为什么某些文本框默认不接受 Control + A 快捷键以全选

但是那个答案对我不起作用。我有这段代码:

public class LoginForm : Form
{
    private TextBox tbUsername;

    public LoginForm()
    {
        tbUsername = new TextBox();
        tbUsername.ShortcutsEnabled = true;
        tbUsername.Multiline = false;
        Controls.Add(tbUsername);
    }
}

文本框出现了,我可以在上面写字,可以剪切、复制和粘贴文本而没有任何问题。 但是当我尝试按下Ctrl+A时,我只听到一个类似于从空文本框中尝试擦除文本时所听到的"叮"声(请在浏览器的地址栏中尝试)。


就我而言,你的代码可以正常工作。我可以使用“CTRL + A”和其他快捷键。我认为“shift + up arrow”应该是选择一个字母,而“shift and end”则选择所有内容。 - keyboardP
是的,它对我也起作用了。你使用的 .net 版本是什么? - spajce
@spajce "目标框架:.NET Framework 4.5",所以我猜它相当新... - Patrik Lippojoki
好的,我无法确定这是否真的是一个错误,但我刚刚使用了.NET 4.5进行了测试,你的代码实际上是可以工作的。我可以使用“Ctrl+A”等操作。 - spajce
这基本上就是我所有的代码了,在我的main()函数之上... - Patrik Lippojoki
显示剩余5条评论
9个回答

77

像其他答案所指示的那样,应该调用Application.EnableVisualStyles()。 同时,TextBox.ShortcutsEnabled 应设置为true。但是如果启用了 TextBox.Multiline,则 Ctrl+A 将不起作用 (请参阅MSDN文档)。使用RichTextBox 可以解决这个问题。


26
有关 MultiLine 的部分必须是在谈论默认行为。将 if (e.Control && e.KeyCode == Keys.A) Textbox.SelectAll(); 放在 KeyDown 事件处理程序中对我来说完全有效。 - Dan Bechard
4
@Dan,没错,如果你正在使用多行文本框且仍需使用标准文本框,则必须像那样绕过它。这是微软一个奇怪的设计决定(可以理解为:“漏洞”)。 - jltrem
5
显然在4.7版本中再次出现了故障。 - Atario
TextBoxRichTextBox都是从TextBoxBase派生而来。它们都有一个ShortcutsEnabled属性,但至少在ctrl-a方面似乎没有任何效果。RichTextBox有一个RichTextShortcutsEnabled属性,但它是不可访问的,但也许在底层启用了RichTextBox的ctrl-a快捷键。 - Al Lelopath

43

只需为该文本框创建一个“keydown”事件,并包含以下代码:

private void tbUsername_KeyDown(object sender, KeyEventArgs e)
{
    if (e.Control && e.KeyCode == Keys.A)
    {
        if (sender != null)
            ((TextBox)sender).SelectAll();
    }
}

如果您的代码中有Application.EnableVisualStyles(),但CTRL+A仍然无法正常工作,那么这是一个非常好的解决方法。 - NeverStopLearning

24

你可以通过覆盖处理命令键来获得所需的结果。

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    const int WM_KEYDOWN = 0x100;
    var keyCode = (Keys) (msg.WParam.ToInt32() &
                          Convert.ToInt32(Keys.KeyCode));
    if ((msg.Msg == WM_KEYDOWN && keyCode == Keys.A) 
        && (ModifierKeys == Keys.Control) 
        && tbUsername.Focused)
    {
        tbUsername.SelectAll();
        return true;
    }            
    return base.ProcessCmdKey(ref msg, keyData);
}

2
这是一个快速且简单的解决方案,适用于那些无法使用"Application.EnableVisualStyles();"的情况。非常有用,谢谢。 - Lars
如果您希望即使TextBox不是具有焦点的控件也能正常工作,那么请删除代码 "&& tbUsername.Focused" 并在 .SelectAll() 调用后添加此语句:"tbUsername.Focus();"。请参见这里:https://dev59.com/zGMl5IYBdhLWcg3w3aPj - RenniePet

6
快速回答是,如果您使用了multiline true,那么您必须明确调用全选功能。
private void tbUsername_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.A && e.Control)
    {
        tbUsername.SelectAll();
    }
}

3

我也遇到过这种情况,我猜你从程序中删除了对Application.EnableVisualStyles(); 的调用?把它添加回Main()函数中,一切都应该能正常工作。


谢谢,问题已解决。有没有一种方法只针对一个表单进行操作,就像这样 MyForm.EnableVisualStyles(); - Patrik Lippojoki
8
我不确定这是否是正确答案,因为我的项目在主程序中添加了这行代码,但CTRL+A无法正常工作。很奇怪... - Junior Mayhé
同样的问题,对我也不起作用。Application.EnableVisualStyles()已经存在,但Ctrl+A无法使用,Ctrl+C也有点奇怪。 - Morvael

1

文本框有一个方法SelectAll(),在我的情况下效果很好。(.net 4.5)


0

不需要处理WM_KEYDOWN!我知道这里的大多数示例(以及CodeProject和许多其他地方)都说需要处理,但它并不能治愈每当出现未处理的WM_CHAR时导致的哔声。

相反,请尝试这个:

LRESULT CALLBACK Edit_Prc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam){
  if(msg==WM_CHAR&&wParam==1){SendMessage(hwnd,EM_SETSEL,0,-1); return 1;}
  else return CallWindowProc((void*)WPA,hwnd,msg,wParam,lParam);
}

记得通过使用 WPA=SetWindowLong(...) 将 EDIT 控件继承为 Edit_Prc(),其中 WPA 是 CallWindowProc(...) 的窗口过程地址。

通过实验我找到了这个方法。在发现所有在线上的答案都坚持处理 WM_KEYDOWN,并使用 GetKeyState() 以及最后生成更大的代码但无法停止令人烦恼的蜂鸣声之后,我才找到了这个方法。

虽然这个答案与 dotnet 无关,在这种情况下,通常最好抓住重点并解决问题,而不是纠结于一个可能或不可能为您完成此操作的大型代码包装系统的哪个版本,特别是如果您想避免对内置行为进行斗争。


0

这是我的代码,它运行得很好

private void mainSimPlus_KeyDown(object sender, KeyEventArgs e)
            {
                e.Handled = true;
                if (e.Control == true && e.KeyCode == Keys.A)
                {
                    if (SelectAllTextBox(txt1))
                        return;
                    if (SelectAllTextBox(txt2))
                        return;
                }
            }
            private bool SelectAllTextBox(TextBox txt)
            {
                if (txt.Focused)
                {
                    txt.SelectAll();
                    return true;
                }
                else
                    return false;
            }

0

我来发表一下我的意见。在按键事件中调用这个函数只是另一种选择。

private void TxtBox_KeyPress(object sender, KeyPressEventArgs e)
{
    if (e.KeyChar == '\x1')
    {
        TxtBox.SelectAll();
        e.Handled = true;
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接