Accelerators

At first glance, this topic seems easy. However, as you'll see later, it generates a lot of questions. An accelerator allows you to select a menu item using keyboard shortcuts (e.g., by pressing predefined key combinations). This feature is convenient . The accelerator table is the resource whose name must match the name of the menu (resource), for which it defines shortcuts. Provided here is an example of such a table. This example defines an accelerator for the MENUP menu item that has the identifier 4.

 MENUP ACCELERATORS     {     VK_F5, 4, VIRTKEY     } 

Here is the general format of the accelerator table:

 Name ACCELERATORS     {     Key 1, Menu item identifier (1) [,type][,parameter]     Key 2, Menu item identifier (2) [,type][,parameter]     Key 3, Menu item identifier (3) [,type][,parameter]     ...     Key N, Menu item identifier (N) [,type][,parameter]     } 

Consider the preceding format. Key is either a character enclosed in quotation marks or ASCII character code or a virtual key. If a character code is used, then the type is specified as ASCII . If a virtual key is used, then the type is defined as VIRTUAL . All names (macro names ) of virtual keys can be found in INCLUDE files ( WINDOWS .H). As usual, I'll define all macro names directly in the program.

The parameter can take one of the following values: NOINVERT , ALT , CONTROL , or SHIFT . The NOINVERT value means that the menu item selected using accelerator isn't highlighted. The values ALT , SHIFT , and CONTROL mean that the corresponding control key must be pressed with the key defined by accelerator. Furthermore, if the key is enclosed in quotation marks, then pressing the CONTROL key is designated by the ^ sign: " ^A ".

Now, look at the working mechanism of accelerators. To ensure that accelerators work, it is necessary to satisfy the following conditions:

  • Accelerator table must be loaded. For this purpose, use the LoadAccelerators function.

  • Messages arriving from accelerator must be converted into the WM_COMMAND message. Here, the TranslateAccelerator function will be useful.

Now, concentrate your attention on the second condition. The TranslateAccelerator function converts WM_KEYDOWN and WM_SYSKEYDOWN into WM_COMMAND and WM_SYSCOMMAND messages, respectively. In this case, the distinguishing feature of accelerator is that the most significant word of WPARAM must contain 1. The least significant word, as you recall, must contain the identifier of the menu item. A question might arise:Why do you need two messages, WM_COMMAND and WM_SYSCOMMAND ? The WM_SYSCOMMAND message is generated to the items of the system menu or window menu (Fig. 9.1).

image from book
Figure 9.1: Window menu

The TranslateAccelerator function returns a nonzero value if accelerator translation was carried out; otherwise , it returns zero. Thus, it is natural to include the call to this function in the message-processing loop. The fragment provided here illustrates this:

 MSG_LOOP:         PUSH 0         PUSH 0         PUSH 0         PUSH OFFSET MSG         CALL GetMessageA@16         CMP  EAX, 0         JE   END_LOOP         PUSH OFFSET MSG         PUSH [ACC]         PUSH [NEWHWND]         CALL TranslateAcceleratorA@12         CMP  EAX, 0         JNE  MSG_LOOP         PUSH OFFSET MSG         CALL TranslateMessage@4         PUSH OFFSET MSG         CALL DispatchMessageA@4         JMP  MSG_LOOP END_LOOP: 

You have already encountered this fragment; however, now it includes the TranslateAccelerator function. The first parameter of this function is the application descriptor; it is followed by the descriptor of the accelerators table ( [ACC] ), which is obtained when loading the table using the LoadAccelerators function. The third parameter is the address containing the message received by the GetMessage function.

At this point, the most interesting things start, because it is possible to say that the message-processing loop is used when the main window is created in a standard way (e.g., by registering the window class and calling the Createwindow function). However, in this chapter, I am describing dialogs. Of course, dialogs can be generated by a standard window, and in this case, everything is normal. However, what should you do in the simplest case when dealing with the only dialog? The first idea that comes to mind is to place the TranslateAccelerator call into the window function and carry out translation on the fly. However, accelerator messages do not arrive to this function.

At this point, you run into at the new material: modal and modeless windows.



The Assembly Programming Master Book
The Assembly Programming Master Book
ISBN: 8170088178
EAN: 2147483647
Year: 2004
Pages: 140
Authors: Vlad Pirogov

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net