简体   繁体   English

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

[英]vb.net Can't set focus to windows form textbox

I've tried every suggestion I could think of or could find online to solve this problem, without success. 我尝试了所有我能想到的建议或可以在网上找到的解决此问题的建议,但都没有成功。

I use ShowDialog to display a form. 我使用ShowDialog显示表单。 The first time the form is displayed, it works OK - the first textbox has a blinking cursor and is ready for input. 第一次显示该表单时,它可以正常工作-第一个文本框的光标闪烁并且可以输入。 The form is closed by one of two buttons or the ControlBox "X". 通过两个按钮之一或ControlBox“ X”关闭该表单。 Every time the form is displayed after the first time, the cursor is in the textbox, but is frozen. 第一次之后每次显示表单时,光标都在文本框中,但被冻结。 Pressing almost any key will unfreeze the cursor, but the Enter key, spacebar, and up and down arrows all bring up the form's context menu ("Restore", "Move", ... , "X Close") instead. 几乎按任何键都可以解冻光标,但是Enter键,空格键和向上和向下箭头都可以调出窗体的上下文菜单(“还原”,“移动”,...,“ X关闭”)。 Removing the ControlBox solves the problem (Setting "ControlBox" to False in Properties window), but I don't want to do that. 删除ControlBox可解决问题(在“属性”窗口中将“ ControlBox”设置为False),但我不想这样做。 Possibly the ControlBox has the focus??? 可能ControlBox具有焦点???

Initially, if the form was closed using a button, that button had focus the next time the form was opened . 最初,如果使用按钮关闭了表单,则下次打开表单时,该按钮将成为焦点。 I added the line Me.ActiveControl = TextBox1 to the form's Load event. 我将Me.ActiveControl = TextBox1行添加到窗体的Load事件。 This prevented the buttons from having focus. 这使按钮无法获得焦点。 I also tried adding Me.Show before Me.ActiveControl = TextBox1 , but it had no effect. 我还尝试在Me.ActiveControl = TextBox1之前添加Me.Show ,但这没有任何效果。 I tried setting the active control in the form's Activated and Shown event handlers, but it made no difference. 我尝试在窗体的Activated和Shown事件处理程序中设置活动控件,但没有区别。 I also tried TextBox1.Select() and TextBox1.Focus() without success. 我也尝试了TextBox1.Select()TextBox1.Focus()但没有成功。

Here is a simple program that demonstrates the problem. 这是一个演示该问题的简单程序。 There are two Windows forms. 有两种Windows窗体。 In the design window, I added a DataGridView (with one column) and a Button to Form1. 在设计窗口中,我向Form1添加了一个DataGridView(带有一列)和一个Button。 Here is the code for 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

For Form2, I added 2 textboxes and an "OK" button in the design window. 对于Form2,我在设计窗口中添加了2个文本框和一个“确定”按钮。 The button is not set as the form's Accept or Cancel button. 该按钮未设置为表单的“接受”或“取消”按钮。 Here's the code: 这是代码:

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

If you press the button on Form1, it always brings up Form2 with the cursor blinking in TextBox1. 如果您按Form1上的按钮,它总是在光标在TextBox1中闪烁的情况下弹出Form2。 In Form2, press the "OK" button or the ControlBox "X" to close it. 在Form2中,按“确定”按钮或ControlBox“ X”将其关闭。 No problem there. 没问题。

The problem happens if you go into a cell in the DataGridView, enter edit mode, and press F10 (or F11). 如果您进入DataGridView中的单元格,进入编辑模式,然后按F10(或F11),则会发生问题。 The first time it brings up Form2 correctly, but if you close Form2, then press F10 again (while editing DataGridView1), Form2 is displayed with the cursor frozen. 第一次正确启动Form2,但是如果关闭Form2,然后再次按F10(在编辑DataGridView1时),则会显示Form2,并且光标处于冻结状态。 At this point, if you press Enter or the spacebar or the up or down arrow keys, the "Restore", "Move", ... , "Close" system menu pops up. 此时,如果按Enter键或空格键或向上或向下箭头键,将弹出“恢复”,“移动”,...,“关闭”系统菜单。

Later Edit: I discovered two pretty strange things - 后来编辑:我发现了两个非常奇怪的东西-

  1. If I close Form2 without using the mouse (ie Tab to the OK button and press Enter) the problem doesn't happen. 如果我不使用鼠标就关闭Form2(即,按Tab键进入“确定”按钮,然后按Enter键),则不会发生此问题。 It only happens if I click on the OK button with the mouse. 仅当我用鼠标单击“确定”按钮时才会发生。

  2. If I bring up Form2 by pressing Button1 instead of pressing F10 and then press and release the Alt key, the cursor freezes and the same four keys bring up the system menu. 如果我通过按Button1而不是按F10调出Form2,然后按并释放Alt键,则光标将冻结,并且相同的四个键调出系统菜单。 It turns out this works in other programs (I'm using XP), not just mine, provided there is no menustrip on the form. 事实证明,这可以在其他程序(我正在使用XP)中工作,而不仅仅是我的,只要表格上没有菜单栏即可。 I'm guessing this is an accessibility feature. 我猜这是一个可访问性功能。 So now my question is: Why is this program acting as if the Alt key was pressed and is there a way to prevent or correct it? 所以现在我的问题是:为什么该程序的行为就像按下Alt键一样,有什么方法可以防止或纠正它?

What I didn't know is that The F10 key (like the Alt key) changes the focus of a form to the menu (if there is one) or the Title Bar icon (if there is one). 我不知道的是F10键(如Alt键)将窗体的焦点更改为菜单(如果有)或标题栏图标(如果有)。 I added a menustrip with the standard items to Form2 just to verify that this is the case. 我向Form2添加了带有标准项的菜单条,只是为了验证是否确实如此。 What I still don't understand is why pressing F10 on Form1 has this effect on Form2. 我仍然不明白的是为什么在Form1上按F10会对Form2产生这种影响。 In any event, adding the following code to Form1 solves the problem. 无论如何,将以下代码添加到Form1中即可解决该问题。 In my actual program, I plan to add this code to my own class derived from DataGridView. 在我的实际程序中,我计划将此代码添加到我自己的从DataGridView派生的类中。 In that case it won't be necessary to make sure that the form's ActiveControl is the datagridview (which I did do in the following code). 在这种情况下,不必确保表单的ActiveControl是datagridview(我在以下代码中做了此操作)。

Basically, I just moved the code for processing F10 from the CellKeyDown sub to ProcessCmdKey, and added Return True to cancel the normal processing of the key. 基本上,我只是将用于处理F10的代码从CellKeyDown子项移至ProcessCmdKey,并添加了Return True来取消键的常规处理。 ProcessCmdKey intercepts the F10 key first, so the other subs (DataGridView1_EditingControlShowing and CellKeyDown) are not needed. 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM