PMGuide - Keyboard Accelerators
Reprint Courtesy of International Business Machines Corporation, © International Business Machines Corporation
A keyboard accelerator (shortcut key to the user) is a keystroke that generates a command message for an application. This chapter describes how to use keyboard accelerators in your PM applications.
About Keyboard Accelerators
Using a keyboard accelerator has the same effect as choosing a menu item. While menus provide an easy way to learn an application's command set, accelerators provide quick access to those commands.
Without accelerators, a user might generate commands by pressing the Alt key to access the menu bar, using the Arrow keys to select an item, then pressing the Enter key to choose the item. In contrast, accelerators allow the user to generate commands with a single keystroke.
Like menu items, accelerators can generate WM_COMMAND, WM_HELP, and WM_SYSCOMMAND messages. Although, normally, accelerators are used to generate existing commands as menu items, they also can send commands that have no menu-item equivalent.
Accelerator Tables
An accelerator table contains an array of accelerators. Accelerator tables exist at two levels within the operating system: a single accelerator table for the system queue and individual accelerator tables for application windows. Accelerators in the system queue apply to all applications-for example, the F1 key always generates a WM_HELP message. Having accelerators for individual application windows ensures that an application can define its own accelerators without interfering with other applications. An accelerator for an application window can override the accelerator in the system queue. An application can modify both its own accelerator table and the system's accelerator table.
The application can set and query the accelerator table for a specific window or for the entire system. For example, an application can query the system accelerator table, copy it, modify the copied data structures; and then, use the modified copy to set the system accelerator table. An application also can modify its window's accelerator table at run time to respond more appropriately to the current environment.
- Note
- An application that modifies any accelerator table other than its own should maintain the original accelerator table; and, before terminating, restore that table.
Accelerator-Table Resources
You can use accelerators in an application by creating an accelerator-table resource in a resource-definition file. Then, when the application creates a standard frame window, the application can associate that window with the resource.
As specified in a resource-definition file, an accelerator table consists of a list of accelerator items, each defining the keystroke that triggers the accelerator, the command the accelerator generates, and the accelerator's style. The style specifies whether the keystroke is a virtual key, a character, or a scan code, and whether the generated message is WM_COMMAND, WM_SYSCOMMAND, or WM_HELP; WM_COMMAND is the default.
Accelerator-Table Handles
Applications that use accelerator tables refer to them with a 32-bit handle. An application using this handle, by default, can make most API function calls for accelerators without having to account for the internal structures that define the accelerator table. When an application needs to dynamically create or change an accelerator table, it must use the ACCEL and ACCELTABLE data structures.
Accelerator-Table Data Structures
An accelerator table consists of individual accelerator items. Each item in the table is represented by an ACCEL structure that defines the accelerator's style, keystroke, and command identifier. Typically, an application defines these aspects of an accelerator in a resource-definition file, but the ACCEL structure also can be built in memory at run time. An accelerator table is represented by an ACCELTABLE structure that specifies the number of accelerator items in the table, the code page used for the keystrokes in the accelerator items, and an array of ACCEL structures (one for each item in the table). Applications that use ACCELTABLE structures directly must allocate sufficient memory to hold all the items in the table.
Accelerator-Item Styles
An accelerator item has a style that determines what combination of keys produces the accelerator and what command message is generated by the accelerator. An application can specify the following accelerator-item styles in the fs field of the ACCEL structure:
Style | Description |
---|---|
AF_ALT | Specifies that the user must hold down the Alt key while pressing the accelerator key. |
AF_CHAR | Specifies that the keystroke is a character that is translated using the code page for the accelerator table. (This is the default style.) |
AF_CONTROL | Specifies that the user must hold down the Ctrl key while pressing the accelerator key. |
AF_HELP | Specifies that the accelerator generates a WM_HELP message instead of a WM_COMMAND message. |
AF_LONEKEY | Specifies that the user need not press another key while the accelerator key is down. Typically, this style is used with the Alt key to specify that simply pressing and releasing that key triggers the accelerator. |
AF_SCANCODE | Specifies that the keystroke is an untranslated scan code from the keyboard. |
AF_SHIFT | Specifies that the user must hold down the Shift key when pressing the accelerator key. |
AF_SYSCOMMAND | Specifies that the accelerator generates a WM_SYSCOMMAND message instead of a WM_COMMAND message. |
AF_VIRTUALKEY | Specifies that the keystroke is a virtual key-for example, the F1 function key. |
Using Keyboard Accelerators
This section explains how to perform the following tasks:
- Create an accelerator-table resource
- Include an accelerator table in a frame window
- Modify an accelerator table
Creating an Accelerator-Table Resource
The following code fragment shows a typical accelerator-table resource:
ACCELTABLE ID_ACCEL_RESOURCE BEGIN VK_ESC, IDM_ED_UNDO, AF_VIRTUALKEY | AF_SHIFT VK_DELETE, IDM_ED_CUT, AF_VIRTUALKEY VK_F2, IDM_ED_COPY, AF_VIRTUALKEY VK_INSERT, IDM_ED_PASTE, AF_VIRTUALKEY END
This accelerator table has four accelerator items. The first one is triggered when the user presses Shift+Esc, which sends a WM_COMMAND message (the default).
An accelerator table in a resource-definition file has an identifier (ID_ACCEL_RESOURCE in the previous example). You can associate an accelerator-table resource with a standard frame window by specifying the table's idResources parameter of the WinCreateStdWindow function.
An application can load an accelerator table resource-definition file automatically when creating a standard frame window, or it can load the resource independently and associate it with a window or with the entire system.
Including an Accelerator Table in a Frame Window
You can add an accelerator table to a frame window either by using the WinSetAccelTable function or by defining an accelerator-table resource (as shown in the previous section) and creating a frame window with the FCF_ACCELTABLE frame style. The second method is shown in the following code fragment:
HWND hwndFrame,hwndClient; CHAR szClassName[]="MyClass"; CHAR szTitle[]="MyWindow"; ULONG flControlStyle= FCF_MINMAX | /* Min and max buttons */ FCF_SHELLPOSITION | /* System size and position */ FCF_SIZEBORDER | /* Size border */ FCF_TITLEBAR | /* Title bar */ FCF_TASKLIST | /* Task list */ FCF_ACCELTABLE | /* Accelerator table */ FCF_SYSMENU | /* System menu */ FCF_MENU; /* Menu */ hwndFrame=WinCreateStdWindow(HWND_DESKTOP, WS_VISIBLE, &flControlStyle, szClassName, szTitle, 0, (HMODULE)NULL, ID_MENU_RESOURCE, &hwndClient);
Notice that if you set the flControlStyle parameter to the FCF_STANDARD flag, you must define an accelerator-table resource, because FCF_STANDARD includes the FCF_ACCELTABLE flag.
If the window being created also has a menu, the menu resource and accelerator resource must have the same resource identifier; this is because the WinCreateStdWindow function has only one input parameter to specify the resource identifiers for menus, accelerator tables, and icons. If an application creates an accelerator table resource-definition file; then, opens a standard frame window (as shown in the preceding example), the accelerator table is installed automatically in the window's message queue, and keyboard events are translated during the normal processing of events. The application simply responds to WM_COMMAND, WM_SYSCOMMAND, and WM_HELP messages; it does not matter whether these messages come from a menu or an accelerator.
An application also can add an accelerator table to a window by calling the WinSetAccelTable function with an accelerator-table handle and a frame-window handle. The application can call either the WinLoadAccelTable function to retrieve an accelerator table from a resource file or the WinCreateAccelTable function to create an accelerator table from an accelerator-table data structure in memory.
Modifying an Accelerator Table
You can modify an accelerator table, for either your application windows or the system, by doing the following:
- Retrieve the handle of the accelerator table.
- Use that handle to copy the accelerator-table data to an application-supplied buffer.
- Change the data in the buffer.
- Use the changed data to create a new accelerator table.
Then you can use the new accelerator-table handle to set the accelerator table, as outlined in the following list:
- Call WinQueryAccelTable to retrieve an accelerator-table handle.
- Call WinCopyAccelTable with a NULL buffer handle to determine how many bytes are in the table.
- Allocate sufficient memory for the accelerator-table data.
- Call WinCopyAccelTable, with a pointer to the allocated memory.
- Modify the data in the buffer (assuming it has the form of an ACCELTABLE structure).
- Call WinCreateAccelTable, passing a pointer to the buffer with the modified accelerator-table data.
- Call WinSetAccelTable with the handle returned by WinCreateAccelTable.