Why is my .setfocus ignored?
Asked Answered
P

6

10

I have an Access form with a textbox that is meant to allow for repeatedly typing a number, hitting enter, and letting a script do stuff. For speed, the field should keep the focus after DoStuff() is done.

However, while I'm sure that DoStuff() is run, the focus always goes to the next field in the tab order. It's like Me.MyFld.SetFocus is being ignored.

How do I keep the focus on this field after DoStuff() is done?

Private Sub MyFld_KeyDown(KeyCode As Integer, Shift As Integer)  
     If KeyCode = vbKeyReturn Then  
         DoStuff  
         Me.MyFld.SetFocus  
     End If
End Sub
Predetermine answered 24/9, 2013 at 19:32 Comment(4)
try more suitable event - AfterUpdate of the textboxDelores
Have you tried stepping through with the debugger to see if anything else is running after your SetFocus method?Oscillation
@4dmonster, if I use another event, how do I know if the current keypress is the enter key? AfterUpdate doesn't include that and OnKeyPress is for regular characters, not the enter key (or so I've read)Predetermine
@techturtle, That's a good idea. After .SetFocus, it just goes to End if, then End Sub and that's it.Predetermine
O
18

If you look at the order of events for a keypress that would change focus, you can see that it always follows this pattern:

KeyDown → BeforeUpdate → AfterUpdate → Exit → LostFocus

You can re-set the focus anywhere in there and it will still keep following the pattern. So we need to tell it to stop following the pattern. Replace your Me.MyFld.SetFocus with DoCmd.CancelEvent and it should fix your problem. Basically, this just kicks you out of the above pattern, so the Exit and LostFocus events never fire...

Oscillation answered 24/9, 2013 at 21:10 Comment(6)
+1 for giving your source. I have created none of those events for this textbox, so I at first don't see how this matters (perhaps there is an implicit Tab key press in one of them?) However, the 'DoCmd.CancelEvent' works exactly as I wanted :)Predetermine
Those events fire for any project, whether you have added custom code to them or not. Once you have pressed the enter key, it starts this sequence. After it has finished the Exit and LostFocus events on your first TextBox, it will continue to the next control in the tab order and launch it's events: Enter → GotFocus → KeyPress → KeyUpOscillation
I have to ask. After LostFocus executes on the first Textbox, why would it go to the next control in the tab order? The user didn't press Tab, only Enter.Predetermine
@Predetermine - to me, this seems like the most logical thing for a control to do, doesn't it? When users complete and update a field on a form, they are typically about to update the next field on the form immediately thereafter.Zenaidazenana
@techturtle, I have been looking for guidance on which Event to use in different circumstances. This seems to recommend using LostFocus as the first option. Am I drawing faulty conclusions?Ambrosia
@Phillip It depends on what you are trying to do. LostFocus is a good one for many cases because it lets you run code any time you leave a field--common when you want the data updated as you are tabbing around a form. If you want it to run more frequently, such as to match partial strings while they are being typed, then you might consider using KeyPress or Change as the triggering event.Oscillation
S
6

A workaround is moving the focus to another control and then back to the first control. Like this:

Private Sub MyFld_KeyDown(KeyCode As Integer, Shift As Integer)  
    If KeyCode = vbKeyReturn Then  
        DoStuff
        Me.anotherControl.SetFocus
        Me.MyFld.SetFocus  
    End If
End Sub
Schoen answered 30/9, 2013 at 14:19 Comment(0)
L
1
  1. click on access options
  2. select Advanced
  3. select Don't move from Move after enter
  4. click ok

It will work 100%

Lois answered 8/7, 2018 at 8:25 Comment(1)
An interesting approach I don't think I considered or even knew about. However, this setting looks to be global. Since I was developing the db for other users, it would mean another step in the 'installation' process. Also, it would have affected the rest of the forms in the db and any other Access dbs they used (at the time there were a few).Predetermine
R
1

Try removing the whole line for variable_name.SetFocus and simply add: Cancel = True

Private Sub MyFld_KeyDown(KeyCode As Integer, Shift As Integer)  
     If KeyCode = vbKeyReturn Then  
         DoStuff  
         Cancel = True  
     End If
End Sub
Radioactive answered 1/8, 2018 at 3:42 Comment(1)
_KeyDown doesn't have a Cancel parameter.Instanter
P
1

Another solution to the problem that I use in Excel.

Let there exist UserForm1 with the TextBox1 and CommandButton1 controls.

Code in the form module:

    Option Explicit

    Private Sub CommandButton1_Click()
      Unload Me
    End Sub


    Private Sub TextBox1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)

      If KeyCode = vbKeyReturn Then

        'Call DoStuff

        Application.OnTime Now, "'Control_SetFocus """ & Me.Name & """, """ & Me.ActiveControl.Name & """ '"
' The concatenation returns a string:  'Control_SetFocus "UserForm1", "TextBox1"'
      End If

    End Sub

And code in the standard module:

Option Explicit

Sub Control_SetFocus(FormName As String, ControlName As String)
    Dim oUserForm   As Object

    Set oUserForm = GetFormByName(FormName)

    If Not oUserForm Is Nothing Then
        oUserForm.Controls(ControlName).SetFocus
    End If
End Sub


Function GetFormByName(FormName As String) As Object
    Dim oUserForm   As Object
    On Error GoTo ErrHandle

    For Each oUserForm In VBA.UserForms
        If StrComp(oUserForm.Name, FormName, vbTextCompare) = 0 Then
            Exit For
        End If
    Next oUserForm

    If oUserForm Is Nothing Then
        Set oUserForm = UserForms.Add(FormName)
    End If

    Set GetFormByName = oUserForm
    Exit Function
ErrHandle:
    Select Case Err.Number
        Case 424:
            MsgBox "Userform " & FormName & " not exists.", vbExclamation, "Get userform by name"
        Case Else:
            MsgBox Err.Number & ": " & Err.Description, vbCritical, "Get userform by name"
    End Select

End Function

Artik

Priapism answered 27/1, 2019 at 12:50 Comment(0)
A
0

An easy solution that works in Excel is to set the KeyCode to 0. If DoStuff steals the focus then you should also set the focus back:

Private Sub MyFld_KeyDown(KeyCode As Integer, Shift As Integer)  
     If KeyCode = vbKeyReturn Then  
         DoStuff 
         KeyCode = 0
         Me.MyFld.SetFocus  
     End If
End Sub
Allotrope answered 19/9, 2020 at 15:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.