在文本框中检测按下Tab键

20
我试图在TextBox中检测Tab键的按下操作。 我知道Tab键并不会触发KeyDownKeyUpKeyPress事件。 在网上找到了BlackWasp的文章“在Windows窗体中检测Tab键”,他们建议重写ProcessCmdKey,但这也没有起作用。 有没有可靠的方法来检测Tab键按下?
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{

    bool baseResult = base.ProcessCmdKey(ref msg, keyData);

    if (keyData == Keys.Tab && textBox_AllUserInput.Focused)
    {
        MessageBox.Show("Tab key pressed.");
        return true;
    }
    if (keyData == (Keys.Tab | Keys.Shift) && textBox_AllUserInput.Focused)
    {
        MessageBox.Show("Shift-Tab key pressed.");
        return true;
    }

    return baseResult;
}

根据Cody Gray的建议,我将代码更改如下:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
    {
        if (keyData == Keys.Tab && textBox_AllUserInput.Focused)
        {
            MessageBox.Show("Tab key pressed.");        }
        if (keyData == (Keys.Tab | Keys.Shift) && textBox_AllUserInput.Focused)
        {
            MessageBox.Show("Shift-Tab key pressed.");        }

        return base.ProcessCmdKey(ref msg, keyData);
    }

问题在于它无法捕获Tab键按下的事件。

3
是的,ProcessCmdKey()非常可靠。没有人能够察觉到你犯了什么错误。 - Hans Passant
我的代码是:protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { bool baseResult = base.ProcessCmdKey(ref msg, keyData); if (keyData == Keys.Tab && textBox_AllUserInput.Focused) { MessageBox.Show("按下了Tab键。"); return true; } return baseResult; } 我尝试了所有三个答案,但都不起作用。 - user2102327
如果你要重写一个基本实现,就不要调用它。将 base.ProcessCmdKey(...) 移动到函数结尾处。 - Cody Gray
当您想要处理TextBoxTab键时,您可以简单地处理PreviewKeyDown事件,而无需覆盖ProcessCmdKey并检查哪个控件处于焦点! - Reza Aghaei
Cody Gray,很抱歉我还不太熟悉C#。我不知道如何:子类化TextBox并覆盖IsInputKey方法。 - user2102327
2个回答

30

有些键盘按键,如 TABRETURNESC 和方向键等,在某些控件中通常会被忽略,因为它们不被视为输入按键。

您可以处理控件的 PreviewKeyDown 事件来处理这些按键,并将它们设置为输入按键。

private void textBox1_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
    if(e.KeyData == Keys.Tab)
    {
        MessageBox.Show("Tab");
        e.IsInputKey = true;
    }
    if (e.KeyData == (Keys.Tab | Keys.Shift))
    {
        MessageBox.Show("Shift + Tab");
        e.IsInputKey = true;
    }
}

2
@CodyGray 这已经有文档记录了。请阅读文档中的备注部分。既然可以通过这种方式处理Tab键,为什么还需要子类化呢? - Reza Aghaei
1
当然,这是一个有文献记录的hack。:-) 但这并不意味着它不是hack。有很多理由支持子类化、封装、关注点分离和良好设计,其中最重要的是良好的设计。可重用性是另一个引人注目的问题。TextBox的子类可能需要比这段代码多3-4行,这并不需要太大的努力。 - Cody Gray
3
所有这些概念都是好东西,例如关注点分离、封装等。但仅仅为了处理一个制表符就专门子类化一个控件并不是一个好的理由,特别是当原帖作者想要为某个TextBox控件处理该键并在此之后运行一段逻辑时。可以通过简单地使用事件来处理它 :) - Reza Aghaei
1
@CodyGray 他想要在运行特定逻辑后执行某些操作,这更加证明了我们应该使用子类化。 假设 OP 想要运行一个写在其表单类中的方法 F,在继承的 TextBox 中重写 ProcessCmdKey 后应该如何运行该方法呢?当然,这只是一场技术讨论,对 OP 和未来的读者都很有用 :) - Reza Aghaei
1
Cody Gray,很抱歉我还不太熟悉C#。我不知道如何:子类化TextBox并覆盖IsInputKey方法。 - user2102327
显示剩余3条评论

0
你可以使用下面的代码来确定何时按下 TAB 键:
 private void input_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e)
    { 
        // Check here tab press or not
        if (e.KeyCode == Keys.Tab)
        {
           // our code here
        }

        // Check for the Shift Key as well
        if (Control.ModifierKeys == Keys.Shift && e.KeyCode == Keys.Tab) {
           
        }
    }

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