Delphi - Keyboard Shortcuts

Modern applications support a number of keyboard shortcuts - cut, copy, and paste are the most common. In Delphi, the special handling for these is provided through Actions and menus.

Designing and registering Actions is pretty involved and I have a page that describes the basics. However, to just use a generic action to implement shortcut keys for a single application (the topic of this page) is much simpler.

Note that Actions are components, not controls, meaning that they are not displayed at run time. To provide a visual presence, they are usually attached to menus and buttons, and are called when one of those is selected. (The Action property is defined as public in TControl and published in some of the derived control.)

However, the action operates on some other control (the target) - not the menu selection or the button (the client).

Overview | Action properties | Creating a generic action | Copy and Paste | Additional controls


Overview

While it is possible to write your own keyboard handler and have it check for various key strokes, it is much easier to define an action and let it do all the work. Basically, each action can be configured to recognize one keyboard shortcut - like ctrl-C for copy.

In the case where several shortcuts preform the same function - such as ctrl-C and ctrl-Ins - you simply define 2 actions of the same type - one for each shortcut.

Menus items are also associated with keyboard shortcuts but, like actions, they are allowed to be directly associated with only a single shortcut. As a result, when multiple shortcuts are associated with a single menu selection, it makes sense to create 2 actions and to associate one of them with the menu.

Besides being associated with a keyboard shortcut, each action can be associated with any number of menu selections and buttons. One typical application might assign a Copy task to

This is accomplished by creating 2 actions (one per key combination) and then associating one of them with both menu selections and the button. Then, no matter which way the user decides to Copy something, the same code will be called.


Action properties

Actions provide a number of properties that they synchronize over multiple controls. By default, when one of them is changed, then the corresponding property is changed for all the associated controls. Another advantage of Actions is that their update methods (there are several) are called from the Delphi idle loop. At that time, the Action typically checks and sees if it makes sense given the current system state. If it does, then it should set Enabled true, otherwise, set it false. For example Whenever the action's property is changed, it will affect the other associated controls .. even at design time .. unless you have changed the related property in the control. This allows you to override the action's automatic behavior.


Creating a generic action

Delphi provides a number of pre-defined actions for various functions and you can extend that list by adding your own. However, to create a one-of action for just one form, you want to create a generic action and customize it. In the new action, the following properties and events are of interest. Obviously, if you create several actions (shortcuts) to perform some function, you should just point them all to the same OnExecute code. If a button or menu item is associated with this action, then those will also run the same OnExecute code. (Pretty cool!)

The other properties mainly apply with pre-defined actions - Caption and ImageIndex are used to automatically configure buttons and menu selections. Visible, Enabled and Checked are used to automatically synchronize multiple controls at runtime (via the OnUpdate event). For instance, if the clipboard contains the wrong type of data, then you might want to disable a button that pastes data.

When an action is first associated with a button, action.caption is copied to button.caption. After that, if action.caption is edited, then button.caption automatically changes. However, if button.caption is manually changed after the action is assigned, then the new text will be kept and changes to action.caption will no longer affect button.caption. Similar synchronization occurs with the other properties and events - by default, changes to the action affect all associated controls .. unless the property or event is changed after the Action property is assigned.


Copy and Paste

I wanted to copy and paste image data using buttons, menu selections, and keyboard shortcuts. Since I was using a Windows system, I wanted both sets of keys to work. Also, since the application had only one image control, there was no reason to create a generic action that had to search for the right type of control .. so I just hardcoded it! To automatically disable the buttons when appropriate, I included the following and linked them to the actions' OnUpdate events.


Sender

Note that the Sender in TBasicAction.OnUpdate and TBasicAction.OnExecute refers to the Action. This is the relevant code. As a result, your code can modify the action's properties (as shown above) during TBasicAction.OnUpdate.

Associating Sender with the control calling an event is the standard practice for events and, normally, I would not have questioned it. However, Actions are normally associated with a menu or button and, therefore, I think it is necessary to be explicitly clear what Sender refers to.

The association is explicitly documented in the help for TBasicAction.Execute and is implied in the TBasicAction.OnUpdate example. However, it is not documented in the help for these two events.

The corollary of this is that in Delphi 5 there is no way to determine how the action was triggered - hotkey, menu, button - not that anyone should care. In Delphi 6, the TBasicAction.ActionComponent property was added so that code in TBasicAction.OnExecute can determine which control initiated the action.


Additional controls

Besides Menus and Actions, these controls are also related to this subject.


Author: Robert Clemenzi
URL: http:// mc-computing.com / Languages / Delphi / Keyboard_Shortcuts.html