How to: Handle your own shortcuts in an application shell
Give an application shell (a main form whose areas are arranged by a WklDockLayout, with a
WklNavBar and a subform that shows the pages) its own keyboard shortcuts, such as Ctrl+1 and
Ctrl+2 to switch pages, Ctrl+N for a new record, and F5 to refresh, that work wherever the focus
is: in a text box on a page, in a WklGrid on a page, or in the shell itself.
Requires WKL Forms Object Library 1.45 or later for ShortcutKeys; the forwarding approach at the
end works with 1.24 or later.
Solution overview
- The shell's
KeyPreviewisn't enough. Keys typed in a subform reach only that subform's form and its controls; the shell'sForm_KeyDownnever sees them. - The layout watches the whole form.
WklDockLayout.ShortcutKeyslists the key combinations in AutoKeys macro notation (^1;^2;^N;{F5}). The layout sees every key the user presses on its form, including in subforms, before Access and the control with the focus do, and raisesShortcutfor any listed key. - One place decides. The shell's
Shortcutprocedure runs the command and setsHandled = True; the key then doesn't reach anything else. A key left withHandled = Falsecontinues as if the layout had never looked at it.
Implementation
In the module of the shell form frmShell (layout layShell, page subform sfPage):
Option Compare Database
Option Explicit
Private Sub Form_Load()
Me!layShell.Object.ShortcutKeys = "^1;^2;^N;{F5}"
End Sub
Private Sub layShell_Shortcut(ByVal Key As String, Handled As Boolean)
Select Case Key
Case "^1"
Me!sfPage.SourceObject = "frmSessions"
Handled = True
Case "^2"
Me!sfPage.SourceObject = "frmCertificates"
Handled = True
Case "^N"
Me!sfPage.Form!grdList.Object.NewRecord
Handled = True
Case "{F5}"
Me!sfPage.Form!grdList.Object.Requery
Handled = True
End Select
End Sub
You can also set ShortcutKeys in Design view (property sheet, Other tab); it's saved with
the form.
Remarks
Keyalways uses one fixed notation, regardless of how it's written inShortcutKeys: modifiers in the order^+%, and letters in uppercase (^N,+{F2},{ESC}).- A letter or digit without Ctrl (
^) or Alt (%) is rejected when the list is set, because it would fire while the user types. - Choose combinations the controls don't need themselves (among others, the grid uses the arrow keys, Enter, Delete, F2, Ctrl+C, Ctrl++, and Ctrl+-; each control's keys are listed in its reference). A listed key is offered to
Shortcutfirst, even when a control would use it. WklNavBartoggles itself with Ctrl+B (ToggleShortcut), and F6 moves between the layout's areas; both keep working alongsideShortcutKeys.- A modal dialog box or pop-up form in front receives its keys as usual; the layout reports only keys pressed on its own form.
Without a WklDockLayout: forwarding from each page
A shell without a layout has each page forward its keys. The page form sets KeyPreview to Yes
and passes Form_KeyDown (and the KeyDown event of a WKL control that has the focus) to a single
public function in the shell, which returns whether it handled the key:
' Module of a page form with the grid grdCustomers.
Private Sub Form_Load()
Me.KeyPreview = True
End Sub
Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
If Forward(KeyCode, Shift) Then KeyCode = 0
End Sub
Private Sub grdCustomers_KeyDown(KeyCode As Integer, ByVal Shift As Integer)
If Forward(KeyCode, Shift) Then KeyCode = 0
End Sub
Private Function Forward(ByVal KeyCode As Integer, ByVal Shift As Integer) As Boolean
On Error Resume Next
If CurrentProject.AllForms("frmShell").IsLoaded Then
Forward = Forms!frmShell.HandleShortcut(KeyCode, Shift)
End If
End Function
HandleShortcut in the shell compares KeyCode and Shift (for example,
KeyCode = vbKeyN And Shift = acCtrlMask) and returns True for a key it handled.