zoukankan      html  css  js  c++  java
  • 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. Add an m_hAccelTable data member (type HACCEL) to the derived class.
    2. 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.
    3. 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. 

  • 相关阅读:
    阿里云盘上线了,使用中,1T空间,不限速(似乎)!
    在互联网大厂实习,虽然转正了,但编程能力很差,要主动离职吗?
    软件外包商都是黑心的吗?
    招聘信息薪资范围是12-20K,能否要20K的薪资?
    为何没有中文编程?
    为什么银行的IT部门都远离市区?
    想花钱速学互联网行业,大概花两三个月的时间,出来好找工作吗
    Java基础总结,超级全的面试题
    一套基于java的开源车牌识别算法
    Java 最常见的 208 道面试题(第八模块答案)网络
  • 原文地址:https://www.cnblogs.com/marryZhan/p/2213916.html
Copyright © 2011-2022 走看看