How to Safely Disable Controls in Microsoft Access

I *never* set the Enabled property of a form control directly. Instead, I use a convenience function so that I don't have to worry about run-time error 2164.

How to Safely Disable Controls in Microsoft Access

You cannot disable an active control.*

If you try to disable the active control, you will get run-time error 2164, "You can't disable a control while it has the focus."

To avoid the error, set the focus to a different control first.

For a general solution to this problem, you can use my DefocusIfActive function.

Better yet, let's call a convenience function instead of setting the .Enabled property.

Rather than this...

Me.tbMyTextbox.Enabled = IsEnabled

...use this...

SetCtlEnabled Me.tbMyTextbox, IsEnabled

The Code: SetCtlEnabled

The SetCtlEnabled routine wraps the DefocusIfActive procedure so that we avoid run-time error 2164, "You can't disable a control while it has the focus."

'----------------------------------------------------------------------------
' Procedure : SetCtlEnabled
' Author    : Mike Wolfe
' Source    : https://nolongerset.com/setctlenabled/
' Purpose   : Safely sets the Enabled property of a form control.
' Params    - Ctl: The control whose Enabled property is being set.
'           - Enabled: A boolean to indicate whether the control 
'                      should be enabled or not.
'           - FallbackCtl: The control to receive focus if the original 
'                          Ctl has focus and is being disabled.
' Notes     : If FallbackCtl is not provided, the function will cycle through
'               the form's controls collection looking for a suitable
'               recipient of the focus.
'----------------------------------------------------------------------------
Sub SetCtlEnabled(Ctl As Control, Enabled As Boolean, _
                  Optional FallbackCtl As Control)
    If Enabled Then
        'It's always safe to enable a control
        Ctl.Enabled = True
    Else
        'https://nolongerset.com/defocusifactive/
        DefocusIfActive Ctl, FallbackCtl
        Ctl.Enabled = False
    End If
End Sub

*UPDATE: Behavior Change

According to this article from Access MVP Colin Riddington, Microsoft quietly changed this behavior (emphasis mine):

For as long as I can remember, I’ve always moved the focus to another control in order to disable the first control. This had always seemed completely logical to me.

However a recent comment by pdanes in this thread at  Access World Forums : Disable ALL controls on form led me to re-check this behaviour.

I can confirm that although that had to be done up to Access 2007, from Access 2010 onwards, it is no longer necessary to move the focus before disabling a control.

That said, I don't think I'll be changing my ways any time soon.  It's not clear to me where exactly the focus goes under the new behavior, so I'll stick with the code I know.

Additional reading

How to Safely Hide Controls in Microsoft Access
I *never* set the Visible property of a form control directly. Instead, I use a convenience function so that I don’t have to worry about run-time error 2165.

Cover image created with Microsoft Designer

All original code samples by Mike Wolfe are licensed under CC BY 4.0