ARWEN emulates support for Accelerator keys. These are user-defined key combinations that are generally used to bypass menu navigations and jump directly to a desired operation. Although there is support for Accelerator keys inside the API I was never able to get it working. Instead, I had to write my own system for managing this capability. A downside is that the key combinations are limited to "ALT + key" pairings (ie, CTRL & SHIFT are ignored). The first way to register an Accelerator key is indirectly when creating the control by inserting the Ampersand character immediately before the character you nominate as the accelerator, ie:
id = create(Button, "&Open",..) -- ALT + 'O'Now, whenever the owner window is open and has the focus (ie, either on itself or any child controls belonging to it), pressing this combination will cause a WM_COMMAND message to be sent to the child control's handler. In effect, the behaviour is mimicking a keypress or mouse click on that control. The caption on the control will indicate the accelerator key with an underline. Because of the process & various limitations the key nomination is NOT case sensitive.
Only one key may be nominated this way. However, you may directly specify any number of accelerators for any control by invoking:
void = setAccelerator(integer id, object caption)
ID
naturally refers to the control
and although it can be of any type it is best to use
"clickable" controls to avoid confusion.
caption
can be (i) a virtual key code
integer or (ii) a length=1 sequence containing the ASCII code or
(iii) a length>1 sequence containing the control' caption in
the same format as used in the create() example above.
If this call succeeds the result will be True otherwise False. A
failed call could happen where 2 controls, both having the same
window owner, attempt to nominate the same accelerator key.
Nominating keys normally used by Window's own accelerated functions is highly unwise
because you might lose keyboard control for some important functions.
In the control handler that receives the WM_COMMAND message as
the result of an Accelerator the
lParam
will be 1 otherwise it will be 0.
If the handler returns a 0 (default) then the focus will be
placed onto the control associated with the Accelerator. If that
control is not a focussable kind then the next available,
focussable control will be sought instead. This behaviour could
have esoteric consequences if the nominated control is, say, a
menu because the next available control is unlikely to be related
and hence moving the focus to that control doesn't serve a useful
purpose. Any return value other than 0 will prevent the focus
moving from it's original position. In most cases the user will
not want the focus to move, therefore the usual return value will
be, say, 1.
If the nominated control is disabled the Accelerator will not fire.
Menus & Accelerators
It seems that because
Windows' manages the Menu loop itself, it will exhibit the
actions of Access keys for Menus which is easily confused with
Accelerator keys. Since I cannot alter the behaviour of Menus in
this regard I thought it'd be better to only allow Accelerator
keys for Menus via setAccelerator(). Therefore, when the user
creates an accelerated control the key underscore & linking
will be done automatically. However, when the control is a menu
only the underscore will automatically show and Windows will use
the nominated key as an Access key (to quickly jump along menu
navigations). Linking a menu to an Accelerator must be done
explicitly, using a different key combination, eg:
id = create(MenuItem, "&File (ALT+F1)",..) -- caption is:
File (ALT+F1)
setAccelerator(id,VK_F1) -- link to accelerator key