MFC Windows 程序设计->键盘加速键

 

As you design your application's menus, you have the option of using keyboard accelerators to assign shortcut keys to any or all of the menu items. An accelerator produces a WM_COMMAND message just as making a menu selection does. Adding keyboard accelerators to your application is simplicity itself. You create an accelerator table resource—a special resource that correlates menu item IDs to keys or combinations of keys—and load the resource into your program with a function call. If the application's main window is a frame window, Windows and the framework do the rest, automatically trapping presses of accelerator keys and notifying your application with WM_COMMAND messages.

An accelerator table resource is defined by an ACCELERATORS block in an RC file. Here is the general format:

 ResourceID ACCELERATORS
BEGIN
  
END

ResourceID is the accelerator table's resource ID. The statements between BEGIN and END identify the accelerator keys and the corresponding menu item IDs. The MFC AppWizard generates accelerator tables using the following format:

IDR_MAINFRAME ACCELERATORS PRELOAD MOVEABLE
BEGIN
    "N",            ID_FILE_NEW,            VIRTKEY,CONTROL
    "O",            ID_FILE_OPEN,           VIRTKEY,CONTROL
    "S",            ID_FILE_SAVE,           VIRTKEY,CONTROL
    "Z",            ID_EDIT_UNDO,           VIRTKEY,CONTROL
    "X",            ID_EDIT_CUT,            VIRTKEY,CONTROL
    "C",            ID_EDIT_COPY,           VIRTKEY,CONTROL
    "V",            ID_EDIT_PASTE,          VIRTKEY,CONTROL
    VK_BACK,        ID_EDIT_UNDO,           VIRTKEY,ALT
    VK_DELETE,      ID_EDIT_CUT,            VIRTKEY,SHIFT
    VK_INSERT,      ID_EDIT_COPY,           VIRTKEY,CONTROL
    VK_INSERT,      ID_EDIT_PASTE,          VIRTKEY,SHIFT
END

In this example, IDR_MAINFRAME is the accelerator table's resource ID. PRELOAD and MOVEABLE are load options that, like the equivalent keywords in MENU statements, have no effect in the Win32 environment. Each line in the table defines one accelerator. The first entry in each line defines the accelerator key, and the second identifies the corresponding menu item. The VIRTKEY keyword tells the resource compiler that the first entry is a virtual key code, and the keyword following it—CONTROL, ALT, or SHIFT—identifies an optional modifier key. In this example, Ctrl-N is an accelerator for File-New, Ctrl-O is an accelerator for File-Open, and so on. The Edit menu's Undo, Cut, Copy, and Paste functions each have two accelerators defined: Ctrl-Z and Alt-Backspace for Undo, Ctrl-X and Shift-Del for Cut, Ctrl-C and Ctrl-Ins for Copy, and Ctrl-V and Shift-Ins for Paste.

Like menus, keyboard accelerators must be loaded and attached to a window before they'll do anything. For a frame window, LoadAccelTable does the loading and attaching in one step:

 

LoadFrame also does the job nicely. In fact, the same function call that loads the menu also loads the accelerator table if the two resources share the same ID:

 

For accelerators to work, the message loop must include a call to the API function ::TranslateAccelerator, as shown here:

 

MFC's CFrameWnd class handles this part for you. Specifically, it overrides the virtual PreTranslateMessage function that it inherits from CWnd and calls ::TranslateAccelerator if it sees an accelerator table has been loaded—that is, if the frame window's m_hAccelTable data member contains a non-NULL accelerator table handle. Not surprisingly, LoadAccelTable loads an accelerator resource and copies the handle to m_hAccelTable. LoadFrame does the same by calling LoadAccelTable.

Accelerators must be handled differently when loaded for nonframe windows that lack the accelerator support in CFrameWnd. Suppose you derive a custom window class from CWnd and want to use accelerators, too. Here's how you'd go about it:

  1.  

  2. Add an m_hAccelTable data member (type HACCEL) to the derived class.

     

     

  3. Early in your application's lifetime, use the API function ::LoadAccelerators to load the accelerator table. Copy the handle returned by ::LoadAccelerators to m_hAccelTable.

     

     

  4. In the window class, override PreTranslateMessage and call ::TranslateAccelerator with the handle stored in m_hAccelTable. Use the value returned by ::TranslateAccelerator as the return value for PreTranslateMessage so that the message won't be translated and dispatched if ::TranslateAccelerator has dispatched it already.

     

    Here's how it looks in code:

 

With this framework in place, a CWnd-type window will use accelerators just as a frame window does. Note that accelerators loaded with ::LoadAccelerators (or LoadAccelTable) don't need to be deleted before termination because Windows deletes them automatically.

Using accelerators to provide shortcuts for commonly used menu commands is preferable to processing keystroke messages manually for two reasons. The first is that accelerators simplify the programming logic. Why write WM_KEYDOWN and WM_CHAR handlers if you don't have to? The second is that if your application's window contains child windows and a child window has the input focus, keyboard messages will go to the child window instead of the main window. (Child windows are discussed in Chapter 7.) As you learned in Chapter 3, keyboard messages always go to the window with the input focus. But when an accelerator is pressed, Windows makes sure the resulting WM_COMMAND message goes to the main window even if one of its children has the input focus.

Accelerators are so useful for trapping keystrokes that they're sometimes used apart from menus. If you want to be notified any time the Ctrl-Shift-F12 combination is pressed, for example, simply create an accelerator for that key combination with a statement like this one:

VK_F12, ID_CTRL_SHIFT_F12, VIRTKEY, CONTROL, SHIFT

Then map the accelerator to a class member function by adding an

ON_COMMAND (ID_CTRL_SHIFT_F12, OnCtrlShiftF12)

entry to the message map. Presses of Ctrl-Shift-F12 will thereafter activate OnCtrlShiftF12, even if no menu item is assigned the ID ID_CTRL_SHIFT_F12. 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值