【问题标题】:vb.net Can't set focus to windows form textboxvb.net 无法将焦点设置到 Windows 窗体文本框
【发布时间】:2014-01-07 23:09:49
【问题描述】:

我已经尝试了所有我能想到或在网上找到的解决这个问题的建议,但没有成功。

我使用 ShowDialog 来显示一个表单。第一次显示表单时,它工作正常 - 第一个文本框有一个闪烁的光标,可以输入。窗体由两个按钮之一或 ControlBox "X" 关闭。每次在第一次之后显示表单时,光标都在文本框中,但被冻结。按下几乎任何键都会解冻光标,但 Enter 键、空格键和上下箭头都会调出表单的上下文菜单(“Restore”、“Move”、...、“X Close”)。删除 ControlBox 可以解决问题(在“属性”窗口中将“ControlBox”设置为 False),但我不想这样做。可能是 ControlBox 有焦点???

最初,如果使用按钮关闭表单,则该按钮会在下次打开表单时获得焦点。我将Me.ActiveControl = TextBox1 行添加到表单的Load 事件中。这阻止了按钮获得焦点。我也尝试在Me.ActiveControl = TextBox1 之前添加Me.Show,但没有效果。我尝试在表单的 Activated 和 Shown 事件处理程序中设置活动控件,但没有任何区别。我也尝试了TextBox1.Select()TextBox1.Focus() 没有成功。

这是一个演示问题的简单程序。有两种 Windows 窗体。在设计窗口中,我向 Form1 添加了一个 DataGridView(一列)和一个 Button。这是Form1的代码:

Public Class Form1
    Private Sub Button1_Click(ByVal sender As System.Object, _
        ByVal e As _System.EventArgs) Handles Button1.Click
        Dim result As DialogResult
        Dim TForm As Form2
        TForm = New Form2
        result = TForm.ShowDialog
    End Sub

    Private Sub DataGridView1_EditingControlShowing _
    (ByVal sender As Object, ByVal e As _
    System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) _
    Handles DataGridView1.EditingControlShowing

        If TypeOf e.Control Is TextBox Then
            RemoveHandler DirectCast(e.Control, TextBox).KeyDown, AddressOf CellKeyDown
            AddHandler DirectCast(e.Control, TextBox).KeyDown, AddressOf CellKeyDown
        End If
    End Sub

    Private Sub CellKeyDown(ByVal sender As Object, ByVal e As KeyEventArgs)
        Select Case e.KeyCode
            Case Keys.F10
                With DataGridView1
                    .EndEdit()
                    Dim result As DialogResult
                    Dim TestForm2 As Form2
                    TestForm2 = New Form2
                    result = TestForm2.ShowDialog
                    TestForm2 = Nothing
                    .BeginEdit(False)
                    Me.ActiveControl = .EditingControl ' This makes the cursor visible
                End With
            Case Keys.F11
                With DataGridView1
                     .EndEdit()
                    Dim result As DialogResult
                    result = Form2.ShowDialog
                    .BeginEdit(False)
                    Me.ActiveControl = .EditingControl
                End With
        End Select
    End Sub

End Class

对于 Form2,我在设计窗口中添加了 2 个文本框和一个“确定”按钮。该按钮未设置为表单的接受或取消按钮。代码如下:

Public Class Form2
    Private Sub btnOK_Click(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles btnOK.Click
        Me.Close()
    End Sub

    Private Sub Form2_Load(ByVal sender As Object, _
    ByVal e As System.EventArgs) Handles Me.Load
        Me.ActiveControl = Me.TextBox1
    End Sub
End Class

如果您按下 Form1 上的按钮,它总是会弹出 Form2,而光标在 TextBox1 中会闪烁。在 Form2 中,按“确定”按钮或控制框“X”将其关闭。没问题。

如果您进入 DataGridView 中的单元格,进入编辑模式,然后按 F10(或 F11),就会出现问题。第一次正确调出 Form2,但如果关闭 Form2,然后再次按 F10(在编辑 DataGridView1 时),则显示 Form2,光标冻结。此时,如果按回车键或空格键或上下箭头键,会弹出“恢复”、“移动”、...、“关闭”系统菜单。

后来编辑:我发现了两件很奇怪的事情-

  1. 如果我在不使用鼠标的情况下关闭 Form2(即 Tab 到 OK 按钮并按 Enter),则不会发生问题。只有当我用鼠标单击 OK 按钮时才会发生这种情况。

  2. 如果我通过按 Button1 而不是按 F10 来调出 Form2,然后按下并释放 Alt 键,光标会冻结,并且相同的四个键会调出系统菜单。事实证明,这适用于其他程序(我使用的是 XP),而不仅仅是我的,只要表单上没有菜单条。我猜这是一个辅助功能。所以现在我的问题是:为什么这个程序的行为就像按下了 Alt 键一样,有没有办法阻止或纠正它?

【问题讨论】:

  • 尝试将 YourTextbox.Focus 放在 Form_Shown 事件上。
  • 贴出相关代码而不是仅仅描述它通常会有帮助。
  • 这很奇怪,在我的作品中......问题是它会在您加载第二个表单时冻结第二次以上,对吗?
  • 对。除非我删除 ControlBox。
  • 您是否尝试过将表单显示为新的表单对象?这应该会在您显示它时重置所有属性。

标签: vb.net datagridview focus controlbox


【解决方案1】:

我不知道的是 F10 键(如 Alt 键)将表单的焦点更改为菜单(如果有的话)或标题栏图标(如果有的话)。我在 Form2 中添加了一个带有标准项目的菜单条,只是为了验证情况是否如此。我仍然不明白的是,为什么在 Form1 上按 F10 会对 Form2 产生这种影响。无论如何,将以下代码添加到 Form1 可以解决问题。在我的实际程序中,我计划将此代码添加到我自己的从 DataGridView 派生的类中。在这种情况下,没有必要确保表单的 ActiveControl 是 datagridview(我在下面的代码中做了)。

基本上,我只是把处理F10的代码从CellKeyDown子移到ProcessCmdKey中,加上Return True取消对key的正常处理。 ProcessCmdKey会先截取F10键,所以其他sub(DataGridView1_EditingControlShowing和CellKeyDown)就不需要了。

Protected Overrides Function ProcessCmdKey(ByRef msg As System.Windows.Forms.Message, ByVal keyData As System.Windows.Forms.Keys) As Boolean
    If TypeOf Me.ActiveControl Is DataGridViewTextBoxEditingControl Then
        If keyData = Keys.F10 Then
            DataGridView1.EndEdit()
            Dim TestForm2 As Form2
            TestForm2 = New Form2
            Dim result As DialogResult
            result = TestForm2.ShowDialog
            TestForm2.Dispose()
            TestForm2 = Nothing
            DataGridView1.BeginEdit(False)
            Me.ActiveControl = DataGridView1.EditingControl
            Return True
        End If
    End If
    Return MyBase.ProcessCmdKey(msg, keyData)
End Function

【讨论】:

    猜你喜欢
    • 2011-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多