Accelerator Keys


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