vb.net无法将焦点设置为Windows窗体文本框

时间:2014-01-07 23:09:49

标签: vb.net datagridview focus controlbox

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

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

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

这是一个演示问题的简单程序。有两种Windows窗体。在设计窗口中,我添加了一个DataGridView(带有一列)和一个Button到Form1。这是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中,按“确定”按钮或ControlBox“X”将其关闭。没问题。

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

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

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

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

1 个答案:

答案 0 :(得分:0)

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

基本上,我只是将处理F10的代码从CellKeyDown子句移动到ProcessCmdKey,并添加了Return True来取消密钥的正常处理。 ProcessCmdKey首先拦截F10键,因此不需要其他子(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