如何让文本框中的回车键作为Tab键使用

23

我有几个文本框,希望按下回车键时可以像按下Tab键一样切换到下一个文本框。请问如何实现这种功能,而且不需要在文本框类中添加任何代码(如果可能的话,不要使用覆盖等方法)?


1
这是一个Web应用程序还是Win Forms应用程序? - kemiller2002
我发现了这个网址:http://www.surpluscode.com/2006/06/15/winforms-process-enter-key-press-as-tab-via-sendkeyssend/。 - Pharabus
1
这对我来说有点不正规 :) - arul
听起来可能有些取巧,但这对我很有效。GetNextControl()没有考虑到窗体上的某些控件可能是不可见或被禁用的。我尝试过做类似于这样的事情,但并不那么容易。因此,我会使用这个解决方案。谢谢Pharabus! - Tom Smykowski
我也是这个查询。谢谢你的提问。 - Sagotharan
13个回答

27

这是我通常使用的代码。 必须在 KeyDown 事件中使用。

if (e.KeyData == Keys.Enter)
{
    e.SuppressKeyPress = true;
    SelectNextControl(ActiveControl, true, true, true, true);
}

更新

另一种方法是发送 "TAB" 键!并覆盖该方法,使其更加容易 :)

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{            
    if (keyData == (Keys.Enter))
    {
        SendKeys.Send("{TAB}");
    }

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

1
+1 我认为 SelectNextControlGetNextControl 更好,因为它会自动跳过 Label、Panel、GroupBox、PictureBox、ProgressBar、Splitter 和 LinkLabel。更多信息请参见 http://msdn.microsoft.com/en-us/library/system.windows.forms.control.selectnextcontrol.aspx - Christian Junk
+1 因为在这里使用 SelectNextControl 使得 Enter 键的行为更像是 Tab 键,如果第三个参数设置为 true,它还会跳过 TabStop 设置为 false 的控件。 - Nikola Novak
1
这个答案非常接近,它包含了你所需的所有代码,但是分散在两个代码片段中。你需要在"ProcessCmdKey"重写中调用SelectNextControl而不是SendKeys.Send("{TAB}")。此外,在这种情况下,ProcessCmdKey应该返回true,这样它就不会继续处理回车键按下事件。另外,你需要设置KeyPreview = true才能调用ProcessCmdKey。 - Bryce Wagner

12

你可以在任何控件的keyDown事件中编写代码:

        if (e.KeyCode == Keys.Enter)
        {

            if (this.GetNextControl(ActiveControl, true) != null)
            {
                e.Handled = true;
                this.GetNextControl(ActiveControl, true).Focus();

            }
        }

GetNextControl 在 Vista 上无法正常工作。

为了在 Vista 上使其正常工作,您需要使用下面的代码替换 this.GetNextControl...:

System.Windows.Forms.SendKeys.Send("{TAB}");

GetNextControl在Windows 10中也无法工作。请使用SendKeys.Send("{TAB}")。 - Athanasios Emmanouilidis

4

你不需要创建一个“回车事件处理程序”

你只需要创建一个“中央”的KeyDown事件:

示例

private void General_KeyDown(object sender, KeyPressEventArgs e)
 {
 if (e.KeyCode == Keys.Enter)
        {

            if (this.GetNextControl(ActiveControl, true) != null)
            {
                e.Handled = true;
                this.GetNextControl(ActiveControl, true).Focus();
            }
        }
}

然后,您需要到设计器中选择所有希望使用Enter键进行循环的文本框(通过按住Ctrl并用鼠标单击文本框进行选择),然后转到事件(如雷声按钮),搜索KeyDown事件并在General_KeyDown中键入。现在,您选择的所有文本框都将具有相同的keydown事件 :) 这使得一切都变得更加容易,因为想象一下一个有100个文本框的表单,您想要用Enter键循环遍历所有文本框...为每个文本框创建一个单独的事件...这不是编写程序的正确方式,也不够整洁。希望它能帮到您!!

3
重要提示:如果控件(如单行文本框)需要关联的按钮控件,而且你每次输入时都会听到令人烦恼的“叮”声或警告声,则使用e.Handled = true并不总是消除噪音/声音/铃声的答案。
如果控件期望有一个关联的按钮来“输入”你的条目,那么你还必须处理“缺失”的控件。
e.Handled = e.SuppressKeyPress = true;

这可能有助于消除“叮”的声音。
就我个人而言,在我的情况下,我的用户需要使用“ENTER键”,因为我们正在从终端/绿屏应用程序过渡到Windows应用程序,他们更习惯于通过字段进行“ENTER”而不是切换选项卡。
所有这些方法都起作用,但仍会发出令人讨厌的声音,直到我添加了e.SuppressKeyPress

3

这对我起了作用

if (e.Key == Key.Enter)
            ((TextBox)sender).MoveFocus(new TraversalRequest(new FocusNavigationDirection()));

6
是的,但您不需要将它转换为TextBox。相反,将其转换为UIElement,然后您可以在每个控件上使用此方法。同时,您应该提到这仅适用于WPF而不是Winforms。 - Oliver
@Oliver:提到它只适用于WPF而不是WinForms,点赞+1。 - Sunny Sharma

2
如果您定义了所有控件的选项卡顺序并使表单的KeyPreview属性为True,则只需要这样做:
    Private Sub frmStart_KeyDown(sender As Object, e As KeyEventArgs) Handles Me.KeyDown
    If e.KeyCode = Keys.Enter Then
        System.Windows.Forms.SendKeys.Send("{TAB}")
    End If
End Sub

1

我在一个文本框的keydown事件中使用了这段代码。

if (e.KeyData == Keys.Enter)
{
     e.SuppressKeyPress = true;
     SelectNextControl(ActiveControl, true, true, true, true);
}

我无法处理表单中所有文本框的keydown事件。请提供建议。谢谢。


我在窗体加载事件中编写了以下代码,但它没有起作用:foreach (System.Windows.Forms.Control cont in this.Controls) { if (cont is TextBox) { cont.KeyDown += new KeyEventHandler(this.txtNo_KeyDown); } } - Shahrzad Saeedi

1
我不在表单级别执行此操作。我创建一个通用方法,将其共享到所有我想要进行此操作的输入框的KeyDown事件中(有一个例外):
       private void alltextBoxes_KeyDown(object sender, KeyEventArgs e)
    {
        try
        {
            if (e.KeyCode == Keys.Enter)
            {
                e.SuppressKeyPress = true;
                SelectNextControl(ActiveControl, true, true, true, true);                    
            }
        }
        catch
        {
        }
    }

如果我正在编写一个控件,希望在其他应用程序中使用,我会像这样为最后一个输入单独创建一个方法:
       private void lastinput_KeyDown(object sender, KeyEventArgs e)
    {
        try
        {
            if (e.KeyCode == Keys.Enter)
            {
                e.SuppressKeyPress = true;
                System.Windows.Forms.SendKeys.Send("{TAB}");
            }
        }
        catch
        {
        }
    }

否则,当您尝试在另一个项目中运行时,控件将仅在其内部循环。您可以在任何地方使用第二种方法,但我认为第一种方法是首选方式。

0

这样更好,因为当你按下回车键时,可以聚焦到下一个选项卡。你需要先设置选项卡顺序。

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (keyData == (Keys.Enter))
            {
                SelectNextControl(ActiveControl, true, true, true, true);
            }

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

目前你的回答不够清晰,请编辑并添加更多细节,以帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何编写好答案的更多信息。 - Community

0

对于那些使用VB编程的人...

Public Class NoReturnTextBox
    Inherits System.Windows.Forms.TextBox

    Const CARRIAGE_RETURN As Char = Chr(13)

    ' Trap for return key....
    Private Sub NoReturnTextBox_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles Me.KeyPress

        If e.KeyChar = CARRIAGE_RETURN Then
            e.Handled = True
            System.Windows.Forms.SendKeys.Send(vbTab)
        End If

    End Sub

End Class

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