PlatformKeyboardEvent::PlatformKeyboardEvent(wxKeyEvent& event) { if (event.GetEventType() == wxEVT_KEY_UP) m_type = KeyUp; else if (event.GetEventType() == wxEVT_KEY_DOWN) m_type = KeyDown; else if (event.GetEventType() == wxEVT_CHAR) m_type = Char; else ASSERT_NOT_REACHED(); if (m_type != Char) m_keyIdentifier = keyIdentifierForWxKeyCode(event.GetKeyCode()); else { //ENTER is an editing command processed as a char (only Enter and Tab are) //unfortunately the unicode key for numpad_enter (370) is NOT what we want here (13) //The unicode values for normal enter and tab are the same as the ASCII values, thus ok //Note that I think this a wx bug, as the Character Code is actually 13 when //numpad_enter is a CHAR event. if (event.GetKeyCode() == 13 && event.GetUnicodeKey() == wxChar(370)) m_text = "\r"; else m_text = wxString(event.GetUnicodeKey()); m_unmodifiedText = m_text; } m_autoRepeat = false; // FIXME: not correct. m_windowsVirtualKeyCode = windowsKeyCodeForKeyEvent(event.GetKeyCode()); m_nativeVirtualKeyCode = event.GetKeyCode(); m_isKeypad = (event.GetKeyCode() >= WXK_NUMPAD_SPACE) && (event.GetKeyCode() <= WXK_NUMPAD_DIVIDE); m_shiftKey = event.ShiftDown(); m_ctrlKey = event.CmdDown(); m_altKey = event.AltDown(); m_metaKey = event.MetaDown(); }
void GSPanel::OnKeyDown( wxKeyEvent& evt ) { // HACK: Legacy PAD plugins expect PCSX2 to ignore keyboard messages on the GS Window while // the PAD plugin is open, so ignore here (PCSX2 will direct messages routed from PAD directly // to the APP level message handler, which in turn routes them right back here -- yes it's // silly, but oh well). #ifdef __linux__ // HACK2: In gsopen2 there is one event buffer read by both wx/gui and pad plugin. Wx deletes // the event before the pad see it. So you send key event directly to the pad. if( (PADWriteEvent != NULL) && (GSopen2 != NULL) ) { keyEvent event; event.key = evt.GetRawKeyCode(); if (evt.GetEventType() == wxEVT_KEY_UP) event.evt = 3; // X equivalent of KEYRELEASE; else if (evt.GetEventType() == wxEVT_KEY_DOWN) event.evt = 2; // X equivalent of KEYPRESS; else event.evt = 0; PADWriteEvent(event); } #endif if( (PADopen != NULL) && CoreThread.IsOpen() ) return; DirectKeyCommand( evt ); }
void KeyMonitorTextCtrl::OnKey(wxKeyEvent &event) { if(event.GetKeyCode() != 308){ //printf("key:%d %d\n", event.GetKeyCode(), event.GetModifiers()); } // backspace cannot be used as shortcut key... if (event.GetKeyCode() == WXK_BACK) { // this text ctrl contains something and the user pressed backspace... // we must delete the keypress... Clear(); return; } if (event.GetEventType() == wxEVT_KEY_DOWN || (event.GetEventType() == wxEVT_KEY_UP && !IsValidKeyComb())) { // the user pressed some key combination which must be displayed // in this text control.... or he has just stopped pressing a // modifier key like shift, ctrl or alt without adding any // other alphanumeric char, thus generating an invalid keystroke // which must be cleared out... KeyBinder::Key key; key.code = event.GetKeyCode(); key.flags = event.GetModifiers(); SetValue(KeyBinder::GetKeyBindingAsText(key)); SetInsertionPointEnd(); } }
bool KeyboardTarget::update_state (wxKeyEvent &ev) { unsigned int keyval = (unsigned int) ev.GetKeyCode(); bool changed = true; if (ev.GetEventType() == wxEVT_KEY_DOWN) { if (find (_state.begin(), _state.end(), keyval) == _state.end()) { _state.push_back (keyval); sort (_state.begin(), _state.end()); } else { changed = false; } } else if (ev.GetEventType() == wxEVT_KEY_UP) { KeyState::iterator i; if ((i = find (_state.begin(), _state.end(), keyval)) != _state.end()) { _state.erase (i); sort (_state.begin(), _state.end()); } } #ifdef DEBUG_KEYBOARD cerr << "STATE: "; for (KeyState::iterator i = _state.begin(); i != _state.end(); ++i) { cerr << name_from_keycode(*i) << ' '; } cerr << " changed: " << changed << endl; #endif return changed; }
void wxKeyMonitorTextCtrl::OnKey(wxKeyEvent &event) { // backspace cannot be used as shortcut key... #ifndef wxKEYBINDER_ALLOW_BACKSPACE if (event.GetKeyCode() == WXK_BACK) { // this text ctrl contains something and the user pressed backspace... // we must delete the keypress... Clear(); return; } #endif if (event.GetEventType() == wxEVT_KEY_DOWN || (event.GetEventType() == wxEVT_KEY_UP && !IsValidKeyComb())) { // the user pressed some key combination which must be displayed // in this text control.... or he has just stopped pressing a // modifier key like shift, ctrl or alt without adding any // other alphanumeric char, thus generating an invalid keystroke // which must be cleared out... SetValue(wxKeyBind::GetKeyStrokeString(event)); SetInsertionPointEnd(); } }
void GSPanel::OnKeyDownOrUp( wxKeyEvent& evt ) { // HACK: Legacy PAD plugins expect PCSX2 to ignore keyboard messages on the GS Window while // the PAD plugin is open, so ignore here (PCSX2 will direct messages routed from PAD directly // to the APP level message handler, which in turn routes them right back here -- yes it's // silly, but oh well). #if defined(__unix__) // HACK2: In gsopen2 there is one event buffer read by both wx/gui and pad plugin. Wx deletes // the event before the pad see it. So you send key event directly to the pad. if( (PADWriteEvent != NULL) && (GSopen2 != NULL) ) { keyEvent event; event.key = evt.GetRawKeyCode(); if (evt.GetEventType() == wxEVT_KEY_UP) event.evt = 3; // X equivalent of KEYRELEASE; else if (evt.GetEventType() == wxEVT_KEY_DOWN) event.evt = 2; // X equivalent of KEYPRESS; else event.evt = 0; PADWriteEvent(event); } #endif #ifdef __WXMSW__ // Not sure what happens on Linux, but on windows this method is called only when emulation // is paused and the GS window is not hidden (and therefore the event doesn't arrive from // the pad plugin and doesn't go through Pcsx2App::PadKeyDispatch). On such case (paused). // It needs to handle two issues: // 1. It's called both for key down and key up (linux apparently needs it this way) - but we // don't want to execute the command twice (normally commands execute on key down only). // 2. It has wx keycode which is upper case for ascii chars, but our command handlers expect // lower case for non-special keys. // ignore key up events if (evt.GetEventType() == wxEVT_KEY_UP) return; // Make ascii keys lower case - this apparently works correctly also with modifiers (shift included) if (evt.m_keyCode >= 'A' && evt.m_keyCode <= 'Z') evt.m_keyCode += (int)'a' - 'A'; #endif if( (PADopen != NULL) && CoreThread.IsOpen() ) return; DirectKeyCommand( evt ); }
void KeyboardTarget::process_key_event (wxKeyEvent &event) { KeyMap::iterator result; bool changed = true; if (!_enabled) { event.Skip(); return; } if (event.GetEventType() == wxEVT_KEY_DOWN) { changed = update_state (event); if (changed) { if (_learning) { // do nothing yet } else if ((result = keymap.find (_state)) != keymap.end()) { (*result).second (false); } else { event.Skip(); } } // if it didn't change, it was an autorepeat, which we ignore } else if (event.GetEventType() == wxEVT_KEY_UP) { if (_learning) { // this is the first key up while learning, commit the binding commit_learn (); _learning = false; LearningStopped(); // emit } else if ((result = keymap.find (_state)) != keymap.end()) { (*result).second (true); } else { event.Skip(); } update_state (event); } }
void wxWebView::OnKeyEvents(wxKeyEvent& event) { WebCore::Frame* frame = 0; if (m_mainFrame) frame = m_mainFrame->GetFrame(); if (frame && frame->view()) { // WebCore doesn't handle these events itself, so we need to do // it and not send the event down or else CTRL+C will erase the text // and replace it with c. if (event.CmdDown() && event.GetEventType() == wxEVT_KEY_UP) { if (event.GetKeyCode() == static_cast<int>('C')) Copy(); else if (event.GetKeyCode() == static_cast<int>('X')) Cut(); else if (event.GetKeyCode() == static_cast<int>('V')) Paste(); else if (event.GetKeyCode() == static_cast<int>('Z')) { if (event.ShiftDown()) { if (m_mainFrame->CanRedo()) m_mainFrame->Redo(); } else { if (m_mainFrame->CanUndo()) m_mainFrame->Undo(); } } } else { WebCore::PlatformKeyboardEvent wkEvent(event); if (wkEvent.type() == WebCore::PlatformKeyboardEvent::Char && wkEvent.altKey()) frame->eventHandler()->handleAccessKey(wkEvent); else frame->eventHandler()->keyEvent(wkEvent); } } // make sure we get the character event. if (event.GetEventType() != wxEVT_CHAR) event.Skip(); }
int AudacityApp::OnAllKeys(wxKeyEvent& event) { AudacityProject *audacityPrj = GetActiveProject(); if (!audacityPrj) { return -1; } if(audacityPrj->IsActive()) { if (event.GetEventType() == wxEVT_KEY_DOWN) { if (audacityPrj->HandleKeyDown(event)) return true; } if (event.GetEventType() == wxEVT_KEY_UP) { if (audacityPrj->HandleKeyUp(event)) return true; } } return -1; }
PlatformKeyboardEvent::PlatformKeyboardEvent(wxKeyEvent& event) { m_text = wxString(event.GetUnicodeKey()); m_unmodifiedText = m_text; m_keyIdentifier = keyIdentifierForWxKeyCode(event.GetKeyCode()); m_isKeyUp = event.GetEventType() == wxEVT_KEY_UP; m_autoRepeat = false; // FIXME: not correct. m_WindowsKeyCode = windowsKeyCodeForKeyEvent(event.GetKeyCode()); m_isKeypad = (event.GetKeyCode() >= WXK_NUMPAD_SPACE) && (event.GetKeyCode() <= WXK_NUMPAD_DIVIDE); m_shiftKey = event.ShiftDown(); m_ctrlKey = event.CmdDown(); m_altKey = event.AltDown(); m_metaKey = event.MetaDown(); }
void reViewport::OnCanvasKeypress(wxKeyEvent& event){ wxEventType eventType = event.GetEventType(); bool handled = false; if (eventType == wxEVT_KEY_DOWN) handled = m_toolManager->OnKeyDown(event, m_glCanvas); else handled = m_toolManager->OnKeyUp(event, m_glCanvas); if (!handled){ event.Skip(); } }
///Call this when a key event is received. ///If it matches a command, it will call the appropriate ///CommandManagerListener function. If you pass any flags, ///the command won't be executed unless the flags are compatible ///with the command's flags. bool CommandManager::HandleKey(wxKeyEvent &evt, wxUint32 flags, wxUint32 mask) { wxString keyStr = KeyEventToKeyString(evt); CommandListEntry *entry = mCommandKeyHash[keyStr]; if (evt.GetEventType() == wxEVT_KEY_DOWN) { return HandleCommandEntry( entry, flags, mask, &evt ); } if (entry && entry->wantevent) { return HandleCommandEntry( entry, flags, mask, &evt ); } return false; }
void wxWebView::OnKeyEvents(wxKeyEvent& event) { WebCore::Frame* frame = 0; if (m_impl->page) frame = m_impl->page->focusController()->focusedOrMainFrame(); if (!(frame && frame->view())) return; if (event.GetKeyCode() == WXK_CAPITAL) frame->eventHandler()->capsLockStateMayHaveChanged(); WebCore::PlatformKeyboardEvent wkEvent(event); if (frame->eventHandler()->keyEvent(wkEvent)) return; //Some things WebKit won't do for us... Copy/Cut/Paste and KB scrolling if (event.GetEventType() == wxEVT_KEY_DOWN) { switch (event.GetKeyCode()) { case 67: //"C" if (CanCopy() && event.GetModifiers() == wxMOD_CMD) { Copy(); return; } break; case 86: //"V" if (CanPaste() && event.GetModifiers() == wxMOD_CMD) { Paste(); return; } break; case 88: //"X" if (CanCut() && event.GetModifiers() == wxMOD_CMD) { Cut(); return; } break; case WXK_INSERT: if (CanCopy() && event.GetModifiers() == wxMOD_CMD) { Copy(); return; } if (CanPaste() && event.GetModifiers() == wxMOD_SHIFT) { Paste(); return; } return; //Insert shall not become a char case WXK_DELETE: if (CanCut() && event.GetModifiers() == wxMOD_SHIFT) { Cut(); return; } break; case WXK_LEFT: case WXK_NUMPAD_LEFT: frame->view()->scrollBy(WebCore::IntSize(-WebCore::Scrollbar::pixelsPerLineStep(), 0)); return; case WXK_UP: case WXK_NUMPAD_UP: frame->view()->scrollBy(WebCore::IntSize(0, -WebCore::Scrollbar::pixelsPerLineStep())); return; case WXK_RIGHT: case WXK_NUMPAD_RIGHT: frame->view()->scrollBy(WebCore::IntSize(WebCore::Scrollbar::pixelsPerLineStep(), 0)); return; case WXK_DOWN: case WXK_NUMPAD_DOWN: frame->view()->scrollBy(WebCore::IntSize(0, WebCore::Scrollbar::pixelsPerLineStep())); return; case WXK_END: case WXK_NUMPAD_END: frame->view()->setScrollPosition(WebCore::IntPoint(frame->view()->scrollX(), frame->view()->maximumScrollPosition().y())); return; case WXK_HOME: case WXK_NUMPAD_HOME: frame->view()->setScrollPosition(WebCore::IntPoint(frame->view()->scrollX(), 0)); return; case WXK_PAGEUP: case WXK_NUMPAD_PAGEUP: frame->view()->scrollBy(WebCore::IntSize(0, -frame->view()->visibleHeight() * WebCore::Scrollbar::minFractionToStepWhenPaging())); return; case WXK_PAGEDOWN: case WXK_NUMPAD_PAGEDOWN: frame->view()->scrollBy(WebCore::IntSize(0, frame->view()->visibleHeight() * WebCore::Scrollbar::minFractionToStepWhenPaging())); return; //These we don't want turning into char events, stuff 'em case WXK_ESCAPE: case WXK_LBUTTON: case WXK_RBUTTON: case WXK_CANCEL: case WXK_MENU: case WXK_MBUTTON: case WXK_CLEAR: case WXK_PAUSE: case WXK_SELECT: case WXK_PRINT: case WXK_EXECUTE: case WXK_SNAPSHOT: case WXK_HELP: case WXK_F1: case WXK_F2: case WXK_F3: case WXK_F4: case WXK_F5: case WXK_F6: case WXK_F7: case WXK_F8: case WXK_F9: case WXK_F10: case WXK_F11: case WXK_F12: case WXK_F13: case WXK_F14: case WXK_F15: case WXK_F16: case WXK_F17: case WXK_F18: case WXK_F19: case WXK_F20: case WXK_F21: case WXK_F22: case WXK_F23: case WXK_F24: case WXK_NUMPAD_F1: case WXK_NUMPAD_F2: case WXK_NUMPAD_F3: case WXK_NUMPAD_F4: //When numlock is off Numpad 5 becomes BEGIN, or HOME on Char case WXK_NUMPAD_BEGIN: case WXK_NUMPAD_INSERT: return; } } event.Skip(); }
static bool wxTranslateGTKKeyEventToWx(wxKeyEvent& event, wxWindowGTK *win, GdkEventKey *gdk_event) { // VZ: it seems that GDK_KEY_RELEASE event doesn't set event->string // but only event->keyval which is quite useless to us, so remember // the last character from GDK_KEY_PRESS and reuse it as last resort // // NB: should be MT-safe as we're always called from the main thread only static struct { KeySym keysym; long keycode; } s_lastKeyPress = { 0, 0 }; KeySym keysym = gdk_event->keyval; wxLogTrace(TRACE_KEYS, _T("Key %s event: keysym = %ld"), event.GetEventType() == wxEVT_KEY_UP ? _T("release") : _T("press"), keysym); long key_code = wxTranslateKeySymToWXKey(keysym, false /* !isChar */); if ( !key_code ) { // do we have the translation or is it a plain ASCII character? if ( (gdk_event->length == 1) || wxIsAsciiKeysym(keysym) ) { // we should use keysym if it is ASCII as X does some translations // like "I pressed while Control is down" => "Ctrl-I" == "TAB" // which we don't want here (but which we do use for OnChar()) if ( !wxIsAsciiKeysym(keysym) ) { keysym = (KeySym)gdk_event->string[0]; } // we want to always get the same key code when the same key is // pressed regardless of the state of the modifiers, i.e. on a // standard US keyboard pressing '5' or '%' ('5' key with // Shift) should result in the same key code in OnKeyDown(): // '5' (although OnChar() will get either '5' or '%'). // // to do it we first translate keysym to keycode (== scan code) // and then back but always using the lower register Display *dpy = (Display *)wxGetDisplay(); KeyCode keycode = XKeysymToKeycode(dpy, keysym); wxLogTrace(TRACE_KEYS, _T("\t-> keycode %d"), keycode); KeySym keysymNormalized = XkbKeycodeToKeysym(dpy, keycode, 0, 0); // use the normalized, i.e. lower register, keysym if we've // got one key_code = keysymNormalized ? keysymNormalized : keysym; // as explained above, we want to have lower register key codes // normally but for the letter keys we want to have the upper ones // // NB: don't use XConvertCase() here, we want to do it for letters // only key_code = toupper(key_code); } else // non ASCII key, what to do? { // by default, ignore it key_code = 0; // but if we have cached information from the last KEY_PRESS if ( gdk_event->type == GDK_KEY_RELEASE ) { // then reuse it if ( keysym == s_lastKeyPress.keysym ) { key_code = s_lastKeyPress.keycode; } } } if ( gdk_event->type == GDK_KEY_PRESS ) { // remember it to be reused for KEY_UP event later s_lastKeyPress.keysym = keysym; s_lastKeyPress.keycode = key_code; } } wxLogTrace(TRACE_KEYS, _T("\t-> wxKeyCode %ld"), key_code); // sending unknown key events doesn't really make sense if ( !key_code ) return false; // now fill all the other fields wxFillOtherKeyEventFields(event, win, gdk_event); event.m_keyCode = key_code; #if wxUSE_UNICODE if ( gdk_event->type == GDK_KEY_PRESS || gdk_event->type == GDK_KEY_RELEASE ) { event.m_uniChar = key_code; } #endif return true; }
// This method handles common code for SendKeyDown, SendKeyUp, and SendChar events. void wxApp::MacCreateKeyEvent( wxKeyEvent& event, wxWindow* focus , long keymessage , long modifiers , long when , wxChar uniChar ) { #if wxOSX_USE_COCOA_OR_CARBON short keycode, keychar ; keychar = short(keymessage & charCodeMask); keycode = short(keymessage & keyCodeMask) >> 8 ; if ( !(event.GetEventType() == wxEVT_CHAR) && (modifiers & (controlKey | shiftKey | optionKey) ) ) { // control interferes with some built-in keys like pgdown, return etc. therefore we remove the controlKey modifier // and look at the character after #ifdef __LP64__ // TODO new implementation using TextInputSources #else UInt32 state = 0; UInt32 keyInfo = KeyTranslate((Ptr)GetScriptManagerVariable(smKCHRCache), ( modifiers & (~(controlKey | shiftKey | optionKey))) | keycode, &state); keychar = short(keyInfo & charCodeMask); #endif } long keyval = wxMacTranslateKey(keychar, keycode) ; if ( keyval == keychar && ( event.GetEventType() == wxEVT_KEY_UP || event.GetEventType() == wxEVT_KEY_DOWN ) ) keyval = wxToupper( keyval ) ; // Check for NUMPAD keys. For KEY_UP/DOWN events we need to use the // WXK_NUMPAD constants, but for the CHAR event we want to use the // standard ascii values if ( event.GetEventType() != wxEVT_CHAR ) { if (keyval >= '0' && keyval <= '9' && keycode >= 82 && keycode <= 92) { keyval = (keyval - '0') + WXK_NUMPAD0; } else if (keycode >= 65 && keycode <= 81) { switch (keycode) { case 76 : keyval = WXK_NUMPAD_ENTER; break; case 81: keyval = WXK_NUMPAD_EQUAL; break; case 67: keyval = WXK_NUMPAD_MULTIPLY; break; case 75: keyval = WXK_NUMPAD_DIVIDE; break; case 78: keyval = WXK_NUMPAD_SUBTRACT; break; case 69: keyval = WXK_NUMPAD_ADD; break; case 65: keyval = WXK_NUMPAD_DECIMAL; break; default: break; } } } event.m_shiftDown = modifiers & shiftKey; event.m_rawControlDown = modifiers & controlKey; event.m_altDown = modifiers & optionKey; event.m_controlDown = modifiers & cmdKey; event.m_keyCode = keyval ; #if wxUSE_UNICODE event.m_uniChar = uniChar ; #endif event.m_rawCode = keymessage; event.m_rawFlags = modifiers; event.SetTimestamp(when); event.SetEventObject(focus); #else wxUnusedVar(event); wxUnusedVar(focus); wxUnusedVar(keymessage); wxUnusedVar(modifiers); wxUnusedVar(when); wxUnusedVar(uniChar); #endif }
void wxMultiColumnListCtrl::OnKey(wxKeyEvent& event) { if (event.GetEventType() == wxEVT_KEY_UP) { if (event.GetKeyCode() == GetModifierKey()) { // The window will close, don't select the item under mouse pointer m_ptMouse.x = m_ptMouse.y = -2; SendCloseEvent(); } event.Skip(); return; } if (event.GetKeyCode() == WXK_ESCAPE || event.GetKeyCode() == WXK_RETURN || event.GetKeyCode() == WXK_NUMPAD_ENTER) { // The window will close, don't select the item under mouse pointer m_ptMouse.x = m_ptMouse.y = -2; if (event.GetKeyCode() == WXK_ESCAPE) m_items.SetSelection(-1); SendCloseEvent(); } else if (event.GetKeyCode() == WXK_TAB || event.GetKeyCode() == GetExtraNavigationKey()) { if (event.ShiftDown()) { m_items.SetSelection(m_items.GetSelection() - 1); if (m_items.GetSelection() < 0) m_items.SetSelection(m_items.GetItemCount() - 1); AdvanceToNextSelectableItem(-1); } else { m_items.SetSelection(m_items.GetSelection() + 1); if (m_items.GetSelection() >= m_items.GetItemCount()) m_items.SetSelection(0); AdvanceToNextSelectableItem(1); } GenerateSelectionEvent(); Refresh(); } else if (event.GetKeyCode() == WXK_DOWN || event.GetKeyCode() == WXK_NUMPAD_DOWN) { m_items.SetSelection(m_items.GetSelection() + 1); if (m_items.GetSelection() >= m_items.GetItemCount()) m_items.SetSelection(0); AdvanceToNextSelectableItem(1); GenerateSelectionEvent(); Refresh(); } else if (event.GetKeyCode() == WXK_UP || event.GetKeyCode() == WXK_NUMPAD_UP) { m_items.SetSelection(m_items.GetSelection() - 1); if (m_items.GetSelection() < 0) m_items.SetSelection(m_items.GetItemCount() - 1); AdvanceToNextSelectableItem(-1); GenerateSelectionEvent(); Refresh(); } else if (event.GetKeyCode() == WXK_HOME || event.GetKeyCode() == WXK_NUMPAD_HOME) { m_items.SetSelection(0); AdvanceToNextSelectableItem(1); GenerateSelectionEvent(); Refresh(); } else if (event.GetKeyCode() == WXK_END || event.GetKeyCode() == WXK_NUMPAD_END) { m_items.SetSelection(m_items.GetItemCount() - 1); AdvanceToNextSelectableItem(-1); GenerateSelectionEvent(); Refresh(); } else if (event.GetKeyCode() == WXK_LEFT || event.GetKeyCode() == WXK_NUMPAD_LEFT) { wxSwitcherItem& item = m_items.GetItem(m_items.GetSelection()); int row = item.GetRowPos(); int newCol = item.GetColPos() - 1; if (newCol < 0) newCol = (m_items.GetColumnCount() - 1); // Find the first item from the end whose row matches and whose column is equal or lower int i; for (i = m_items.GetItemCount()-1; i >= 0; i--) { wxSwitcherItem& item2 = m_items.GetItem(i); if (item2.GetColPos() == newCol && item2.GetRowPos() <= row) { m_items.SetSelection(i); break; } } AdvanceToNextSelectableItem(-1); GenerateSelectionEvent(); Refresh(); } else if (event.GetKeyCode() == WXK_RIGHT || event.GetKeyCode() == WXK_NUMPAD_RIGHT) { wxSwitcherItem& item = m_items.GetItem(m_items.GetSelection()); int row = item.GetRowPos(); int newCol = item.GetColPos() + 1; if (newCol >= m_items.GetColumnCount()) newCol = 0; // Find the first item from the end whose row matches and whose column is equal or lower int i; for (i = m_items.GetItemCount()-1; i >= 0; i--) { wxSwitcherItem& item2 = m_items.GetItem(i); if (item2.GetColPos() == newCol && item2.GetRowPos() <= row) { m_items.SetSelection(i); break; } } AdvanceToNextSelectableItem(1); GenerateSelectionEvent(); Refresh(); } else event.Skip(); }