Handling Keyboard Events

team bbl


Keyboard events are represented by the class wxKeyEvent. There are three different kinds of keyboard events in wxWidgets: key down, key up, and character. Key down and up events are untranslated events, whereas character events are translated, which we'll explain shortly. If the key is held down, you will typically get many down events but only one up event, so don't assume that one up event corresponds to each down event.

To receive key events, your window needs to have the keyboard focus, which you can achieve by calling wxWindow::SetFocusfor example, when a mouse button is pressed.

Table 6-2 lists the three keyboard event table macros.

Table 6-2. Keyboard Event Table Macros

EVT_KEY_DOWN(func)

Handles a wxEVT_KEY_DOWN event (untranslated key press).

EVT_KEY_UP(func)

Handles a wxEVT_KEY_UP event (untranslated key release).

EVT_CHAR(func)

Handles a wxEVT_CHAR event (translated key press).


These are the main wxKeyEvent functions that you can use within your key event handler when handling keyboard events.

To get the keycode, call GetKeyCode (in Unicode builds, you can also call GetUnicodeKeyCode). All valid key codes are listed in Table 6-3.

Table 6-3. Key Code Identifiers

WXK_BACK

WXK_RIGHT

WXK_TAB

WXK_DOWN

WXK_RETURN

WXK_SELECT

WXK_ESCAPE

WXK_PRINT

WXK_SPACE

WXK_EXECUTE

WXK_DELETE

WXK_SNAPSHOT

 

WXK_INSERT

WXK_START

WXK_HELP

WXK_LBUTTON

 

WXK_RBUTTON

WXK_NUMPAD0

WXK_CANCEL

WXK_NUMPAD1

WXK_MBUTTON

WXK_NUMPAD2

WXK_CLEAR

WXK_NUMPAD3

WXK_SHIFT

WXK_NUMPAD4

WXK_CONTROL

WXK_NUMPAD5

WXK_MENU

WXK_NUMPAD6

WXK_PAUSE

WXK_NUMPAD7

WXK_CAPITAL

WXK_NUMPAD8

WXK_PRIOR

WXK_NUMPAD9

WXK_NEXT

 

WXK_END

WXK_MULTIPLY

WXK_HOME

WXK_ADD

WXK_LEFT

WXK_SEPARATOR

WXK_UP

WXK_SUBTRACT

WXK_DECIMAL

WXK_PAGEDOWN

WXK_DIVIDE

 
 

WXK_NUMPAD_SPACE

WXK_F1

WXK_NUMPAD_TAB

WXK_F2

WXK_NUMPAD_ENTER

WXK_F3 WXK_F4

WXK_NUMPAD_F1

WXK_F5

WXK_NUMPAD_F2

WXK_F6

WXK_NUMPAD_F3

WXK_F7

WXK_NUMPAD_F4

WXK_F8

WXK_NUMPAD_HOME

WXK_F9

WXK_NUMPAD_LEFT

WXK_F10

WXK_NUMPAD_UP

WXK_F11

WXK_NUMPAD_RIGHT

WXK_F12

WXK_NUMPAD_DOWN

WXK_F13

WXK_NUMPAD_PRIOR

WXK_F14

WXK_NUMPAD_PAGEUP

WXK_F15

WXK_NUMPAD_NEXT

WXK_F16

WXK_NUMPAD_PAGEDOWN

WXK_F17

WXK_NUMPAD_END

WXK_F18

WXK_NUMPAD_BEGIN

WXK_F19

WXK_NUMPAD_INSERT

WXK_F20

WXK_NUMPAD_DELETE

WXK_F21

WXK_NUMPAD_EQUAL

WXK_F22

WXK_NUMPAD_MULTIPLY

WXK_F23

WXK_NUMPAD_ADD

WXK_F24

WXK_NUMPAD_SEPARATOR

 

WXK_NUMPAD_SUBTRACT

WXK_NUMLOCK

WXK_NUMPAD_DECIMAL

WXK_SCROLL

WXK_NUMPAD_DIVIDE

WXK_PAGEUP


To test whether a modifier key is pressed down at the time of generating the event, use AltDown, MetaDown, ControlDown, or ShiftDown. HasModifiers returns true if either Control or Alt was down at the time of the key event (but not the Shift or Meta key states).

Instead of using ControlDown or MetaDown, you may want to use the higher-level CmdDown function that calls MetaDown on Mac OS X and ControlDown on other platforms. See also "Modifier Key Variations" in the following section for further explanation.

GetPosition returns the position of the mouse pointer in client coordinates at the time the event was received.

Tip

If a key down event is caught and the event handler does not call event.Skip(), then the corresponding character event will not happen. If you don't call event.Skip() for events that you don't process in key event function, shortcuts may cease to work on some platforms.


An Example Character Event Handler

Here's the key handler from the wxThumbnailCtrl sample that you can find in examples/chap12/thumbnail on the CD-ROM:

 BEGIN_EVENT_TABLE( wxThumbnailCtrl, wxScrolledWindow )     EVT_CHAR(wxThumbnailCtrl::OnChar) END_EVENT_TABLE() void wxThumbnailCtrl::OnChar(wxKeyEvent& event) {     int flags = 0;     if (event.ControlDown())         flags |= wxTHUMBNAIL_CTRL_DOWN;     if (event.ShiftDown())         flags |= wxTHUMBNAIL_SHIFT_DOWN;     if (event.AltDown())         flags |= wxTHUMBNAIL_ALT_DOWN;     if (event.GetKeyCode() == WXK_LEFT ||         event.GetKeyCode() == WXK_RIGHT ||         event.GetKeyCode() == WXK_UP ||         event.GetKeyCode() == WXK_DOWN ||         event.GetKeyCode() == WXK_HOME ||         event.GetKeyCode() == WXK_PAGEUP ||         event.GetKeyCode() == WXK_PAGEDOWN ||         event.GetKeyCode() == WXK_PRIOR ||         event.GetKeyCode() == WXK_NEXT ||         event.GetKeyCode() == WXK_END)     {         Navigate(event.GetKeyCode(), flags);     }     else if (event.GetKeyCode() == WXK_RETURN)     {         wxThumbnailEvent cmdEvent(             wxEVT_COMMAND_THUMBNAIL_RETURN,             GetId());         cmdEvent.SetEventObject(this);         cmdEvent.SetFlags(flags);         GetEventHandler()->ProcessEvent(cmdEvent);     }     else         event.Skip(); } 

For clarity, the navigation key handling is delegated to a separate function, Navigate. Pressing the Return or Enter key generates a higher-level command event that an application using the control can catch; for all other key presses, Skip is called to enable other parts of the application to process unused key events.

Key Code Translation

Key events provide untranslated key codes, whereas the character event provides a translated key code. The untranslated code for alphanumeric keys is always an uppercase value. For the other keys, it is one of the WXK_XXX values from the keycodes table. The translated key is, in general, the character the user expects to appear as the result of the key combination when typing text into a text entry field.

Here are a few examples to clarify this. When the A key is pressed, the key down event key code is equal to ASCII "A" (65), but the character event key code is ASCII A (97). On the other hand, if you press both the Shift and A keys simultaneously, the key code in the key down event will still be A, while the character event key code will now be A as well.

In this simple case, it is clear that the ASCII code could be found in the key down event handler by checking both the untranslated key code and the value returned by ShiftDown. But in general, if you want the ASCII key code, you should use the character event (with EVT_CHAR) because for non-alphanumeric keys, the translation is dependent on keyboard layout and can only be done properly by the system itself.

Another kind of translation is done when the Control key is pressed: for example, for Ctrl+A, the key down event still passes the same key code A as usual, but the character event will have a key code of 1, which is the ASCII value of this key combination.

You may discover how the other keys on your system behave interactively by running the keyboard sample (samples/keyboard) and pressing keys.

Modifier Key Variations

On Windows, there are Control and Alt modifier keys, and the special Windows key acts as the Meta key. On Unix, the key that acts as Meta is configurable (run xmodmap to see how your system is configured). The Numlock key is sometimes configured as a Meta key, and this is the reason HasModifiers does not return true if the Meta key is downthis allows key presses to be processed normally when Numlock is on.

On Mac OS X, the Command key (with the apple symbol) translates to Meta, while the Option key translates to Alt.

These differences are shown in Table 6-4, with the wxWidgets modifier name shown in the first column, and the key used for this modifier on each of the three major platforms. The Mac's Option and Command keys are illustrated for clarification.

Table 6-4. Modifier Keys Under Windows, Unix, and Mac OS X

Modifier

Key on Windows

Key on Unix

Key on Mac

Shift

Shift

Shift

Shift

Control

Control

Control

Control

Alt

Alt

Alt

Option

Meta

Windows

(Configurable)

Command


Because Mac OS X uses the Command key as a modifier where Control is used on other platforms, you may use wxKeyEvent's CmdDown function instead of ControlDown or MetaDown to catch the appropriate command modifier on each platform.

Note that as well as testing for a modifier key from within an event handler function, you can pass a key code to wxGetKeyState to test whether that key is down.

Accelerators

An accelerator implements a keyboard shortcut for a menu command, enabling the user to execute that command quickly. These shortcuts take precedence over other keyboard processing, such as EVT_CHAR handlers. Standard shortcuts include Ctrl+O to open a file and Ctrl+V to paste data into the application. The easiest way to implement accelerators is to specify them in menu items. For example:

 menu->Append(wxID_COPY, wxT("Copy\tCtrl+C")); 

wxWidgets interprets the text after the "tab" character as an accelerator and adds it to the menu's accelerator table. In this example, when the user presses Ctrl+C the wxID_COPY command is sent, just as though the menu item was selected.

You can use Ctrl, Alt, or Shift in various combinations, followed by a + or - and a character or function key. The following are all valid accelerator specifications: Ctrl+B, G, Shift-Alt-K, F9, Ctrl+F3, Esc, and Del. You can use the following special key names: Del, Back, Ins, Insert, Enter, Return, PgUp, PgDn, Left, Right, Up, Down, Home, End, Space, Tab, Esc, and Escape. Case is not significant when interpreting the names (any combination of uppercase and lowercase will work).

Note that on Mac OS X, a shortcut specification involving Ctrl will actually use the Command key.

Another way to provide accelerators is to populate an wxAccelerator Table with wxAcceleratorEntry objects and associate it with a window using wxWindow::SetAcceleratorTable. Each wxAcceleratorEntry is initialized with a bit-list of modifiers (one or more of wxACCEL_ALT, wxACCEL_CTRL, wxACCEL_SHIFT, and wxACCEL_NORMAL), a key code (see Table 6-3), and an identifier. For example:

 wxAcceleratorEntry entries[4]; entries[0].Set(wxACCEL_CTRL,  (int) 'N',     wxID_NEW); entries[1].Set(wxACCEL_CTRL,  (int) 'X',     wxID_EXIT); entries[2].Set(wxACCEL_SHIFT, (int) 'A',     wxID_ABOUT); entries[3].Set(wxACCEL_NORMAL, WXK_DELETE,   wxID_CUT); wxAcceleratorTable accel(4, entries); frame->SetAcceleratorTable(accel); 

You can use several accelerator tables in a window hierarchy, and you can combine menu string accelerator specifications with an explicit wxAcceleratorTable. This is useful if you have alternative accelerators for a single command, which you cannot entirely specify in the menu item label.

    team bbl



    Cross-Platform GUI Programming with wxWidgets
    Cross-Platform GUI Programming with wxWidgets
    ISBN: 0131473816
    EAN: 2147483647
    Year: 2005
    Pages: 262

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