Accelerator keys are shortcut keys that let the user choose a command from a menu using a single keystroke. For example, an application could let the user select the Delete command simply by pressing the DEL key. Accelerator keys are part of the resource script file, and are tied into the application through the C-language source code.
To provide menu-accelerator keys in your application:
1.In the resource script file, mark the accelerator key for each menu item in the MENUITEM statements.
2.In the resource script file, create an accelerator table. An accelerator table lists the accelerator keys and corresponding menu IDs. You create it using the ACCELERATORS resource statement.
3.In the C-language source file, load the accelerator table by using the LoadAccelerators function.
4.Change the message loop so that it processes accelerator-key messages.
The remainder of this section describes each step in more detail.
The menu text should indicate each item's accelerator key so that the user can tell which key to use. Add the key designations to the MENUITEM definitions in the .RC file.
For example, suppose your application has the following pop-up menu defined in its resource script file:
GroceryMenu MENU
POPUP “&Meats”
BEGIN
MENUITEM “&Beef\tF9”, IDM_BEEF
MENUITEM “&Chicken\tShift+F9”, IDM_CHICKEN
MENUITEM “&Lamb\tCtrl+F9”, IDM_LAMB
MENUITEM “&Pork\tAlt+F9”, IDM_PORK
END
END
The pop-up menu Meats has the four menu items Beef, Chicken, Lamb, and Pork. Each menu item has a mnemonic, indicated by the ampersand (&), and an accelerator key separated from the name with a tab (\t). Whenever a command has a corresponding accelerator, it should be displayed in this way. The accelerator keys in this sample are F9, SHIFT+F9, CTRL+F9, and ALT+F9.
To use accelerator keys, add an accelerator table to the resource script file using the ACCELERATORS statement. The statement lists the accelerator keys and the corresponding menu IDs of the associated commands. In the ACCELERATORS statement, as with other resource statements, BEGIN starts the entry and END marks its end. For example:
GroceryMenu ACCELERATORS
BEGIN
VK_F9, IDM_BEEF, VIRTKEY
VK_F9, IDM_CHICKEN, VIRTKEY, SHIFT
VK_F9, IDM_LAMB, VIRTKEY, CONTROL
VK_F9, IDM_PORK, VIRTKEY, ALT
END
This example defines four accelerator keys, one for each command. The first accelerator key is simply the F9 key; the other three accelerators are keystroke combinations using the ALT, SHIFT, or CTRL key in combination with the F9 key.
Summary: Virtual-key codes provide device-independent key values.
The accelerator keys are defined using the Windows virtual-key code, as indicated by the VIRTKEY option. Virtual keys are device-independent key values that Windows translates for each computer. They are a way to guarantee that the same key is used on all computers without knowing what the actual value of the key is on any computer. You may also use ASCII key codes for accelerators, in which case you would use the ASCII option.
The ACCELERATORS statement associates each accelerator with a menu ID. In the preceding example, the IDM_BEEF, IDM_CHICKEN, IDM_LAMB, and IDM_PORK constants are the menu IDs of the commands on the Grocery menu. When the user presses an accelerator key, these are the values that are passed to the window function.
The accelerator table, like any other resource, needs to be loaded before your application can use it. To load the accelerator table, use the LoadAccelerators function. This function takes a handle to the current instance of the application and the name of the accelerator table (as defined in the .RC file); it returns a handle to the accelerator table for the associated menu. Typically, you load a menu's accelerator table when that menu's window has just been created—that is, within the WM_CREATE case of the window function. For example:
HANDLE hInst; /* handle to current instance */
HANDLE hAccTable; /* handle to accelerator table */
.
.
.
case WM_CREATE:
1 hAccTable = LoadAccelerators (hInst, “GroceryMenu”);
break;
In this example:
1 | This statement loads the accelerator table for GroceryMenu into memory; it assigns the handle identifying the table to the hAccTable variable. The hInst variable identifies the application's resource file; GroceryMenu is the name of the accelerator table. |
Once the table is loaded, the application can use the TranslateAccelerator function to translate accelerators for that menu.
To use the accelerator table, you must add the TranslateAccelerator function to the message loop. When the message loop receives a keyboard-input message containing an accelerator key, TranslateAccelerator converts the message to a WM_COMMAND message containing the appropriate menu ID for that accel-erator, and sends the resulting WM_COMMAND message to the window function.
The message loop should test each message to see if it is an accelerator-key message. If it is, the loop should translate and dispatch the message using TranslateAccelerator. If the message is not an accelerator-key message, the loop should process it normally.
NOTE:
TranslateAccelerator also translates accelerators for commands chosen from the system menu. In such cases, it translates the message into a WM_SYSCOMMAND message.
After you add the TranslateAccelerator function, the message loop should look like this:
while (GetMessage(&msg, NULL, NULL, NULL))
{
1 if(!TranslateAccelerator(hWnd, hAccTable, &msg))
{
2 TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
In this example:
1 | This statement checks each message to see whether it is an accelerator-key message. The window handle, hWnd, identifies the window whose messages are to be translated. The window handle must identify the window that contains the menu with the accelerators. The accelerator handle, hAccTable, specifies the accelerator table to use when translating the accelerators. |
If the message was generated via an accelerator key, the TranslateAccelerator function converts the keystroke to a WM_COMMAND message containing the appropriate menu ID, and sends that WM_COMMAND message to the window function. | |
2 | If the message is not an accelerator-key message, the application processes it as usual, by using the TranslateMessage and DispatchMessage functions. |