bool wxComboBox::MSWProcessEditMsg(WXUINT msg, WXWPARAM wParam, WXLPARAM lParam) { switch ( msg ) { case WM_CHAR: // for compatibility with wxTextCtrl, generate a special message // when Enter is pressed switch ( wParam ) { case VK_RETURN: { if (SendMessage(GetHwnd(), CB_GETDROPPEDSTATE, 0, 0)) return false; wxCommandEvent event(wxEVT_TEXT_ENTER, m_windowId); const int sel = GetSelection(); event.SetInt(sel); event.SetString(GetValue()); InitCommandEventWithItems(event, sel); if ( ProcessCommand(event) ) { // don't let the event through to the native control // because it doesn't need it and may generate an annoying // beep if it gets it return true; } } break; case VK_TAB: // If we have wxTE_PROCESS_ENTER style, we get all char // events, including those for TAB which are usually used // for keyboard navigation, but we should not process them // unless we also have wxTE_PROCESS_TAB style. if ( !HasFlag(wxTE_PROCESS_TAB) ) { int flags = 0; if ( !wxIsShiftDown() ) flags |= wxNavigationKeyEvent::IsForward; if ( wxIsCtrlDown() ) flags |= wxNavigationKeyEvent::WinChange; if ( Navigate(flags) ) return true; } break; } } if ( ShouldForwardFromEditToCombo(msg) ) { // For all the messages forward from the edit control the // result is not used. WXLRESULT result; return MSWHandleMessage(&result, msg, wParam, lParam); } return false; }
bool wxComboBox::MSWProcessEditMsg(WXUINT msg, WXWPARAM wParam, WXLPARAM lParam) { switch ( msg ) { case WM_CHAR: // for compatibility with wxTextCtrl, generate a special message // when Enter is pressed if ( wParam == VK_RETURN ) { if (SendMessage(GetHwnd(), CB_GETDROPPEDSTATE, 0, 0)) return false; wxCommandEvent event(wxEVT_COMMAND_TEXT_ENTER, m_windowId); const int sel = GetSelection(); event.SetInt(sel); event.SetString(GetValue()); InitCommandEventWithItems(event, sel); if ( ProcessCommand(event) ) { // don't let the event through to the native control // because it doesn't need it and may generate an annoying // beep if it gets it return true; } } // fall through case WM_SYSCHAR: return HandleChar(wParam, lParam); case WM_SYSKEYDOWN: case WM_KEYDOWN: return HandleKeyDown(wParam, lParam); case WM_SYSKEYUP: case WM_KEYUP: return HandleKeyUp(wParam, lParam); case WM_SETFOCUS: return HandleSetFocus((WXHWND)wParam); case WM_KILLFOCUS: return HandleKillFocus((WXHWND)wParam); case WM_CUT: case WM_COPY: case WM_PASTE: return HandleClipboardEvent(msg); } return false; }
void wxControlWithItemsBase::SendSelectionChangedEvent(wxEventType eventType) { const int n = GetSelection(); if ( n == wxNOT_FOUND ) return; wxCommandEvent event(eventType, m_windowId); event.SetInt(n); event.SetEventObject(this); event.SetString(GetStringSelection()); InitCommandEventWithItems(event, n); HandleWindowEvent(event); }
void wxChoice::SendSelectionChangedEvent(wxEventType evt_type) { if (!m_hasVMT) return; if (GetSelection() == -1) return; wxCommandEvent event( evt_type, GetId() ); int n = GetSelection(); event.SetInt( n ); event.SetString( GetStringSelection() ); event.SetEventObject( this ); InitCommandEventWithItems( event, n ); HandleWindowEvent( event ); }
bool wxComboBox::MSWProcessEditMsg(WXUINT msg, WXWPARAM wParam, WXLPARAM lParam) { switch ( msg ) { case WM_CHAR: // for compatibility with wxTextCtrl, generate a special message // when Enter is pressed if ( wParam == VK_RETURN ) { if (SendMessage(GetHwnd(), CB_GETDROPPEDSTATE, 0, 0)) return false; wxCommandEvent event(wxEVT_TEXT_ENTER, m_windowId); const int sel = GetSelection(); event.SetInt(sel); event.SetString(GetValue()); InitCommandEventWithItems(event, sel); if ( ProcessCommand(event) ) { // don't let the event through to the native control // because it doesn't need it and may generate an annoying // beep if it gets it return true; } } // fall through, WM_CHAR is one of the message we should forward. default: if ( ShouldForwardFromEditToCombo(msg) ) { // For all the messages forward from the edit control the // result is not used. WXLRESULT result; return MSWHandleMessage(&result, msg, wParam, lParam); } } return false; }
bool wxComboBox::MSWCommand(WXUINT param, WXWORD id) { int sel = -1; wxString value; switch ( param ) { case CBN_DROPDOWN: // remember the last selection, just as wxChoice does m_lastAcceptedSelection = GetCurrentSelection(); { wxCommandEvent event(wxEVT_COMBOBOX_DROPDOWN, GetId()); event.SetEventObject(this); ProcessCommand(event); } break; case CBN_CLOSEUP: // Do the same thing as in wxChoice but using different event type. if ( m_pendingSelection != wxID_NONE ) { SendSelectionChangedEvent(wxEVT_COMBOBOX); m_pendingSelection = wxID_NONE; } { wxCommandEvent event(wxEVT_COMBOBOX_CLOSEUP, GetId()); event.SetEventObject(this); ProcessCommand(event); } break; case CBN_SELENDOK: #ifndef __SMARTPHONE__ // we need to reset this to prevent the selection from being undone // by wxChoice, see wxChoice::MSWCommand() and comments there m_lastAcceptedSelection = wxID_NONE; #endif // set these variables so that they could be also fixed in // CBN_EDITCHANGE below sel = GetSelection(); value = GetStringSelection(); // this string is going to become the new combobox value soon but // we need it to be done right now, otherwise the event handler // could get a wrong value when it calls our GetValue() ::SetWindowText(GetHwnd(), value.t_str()); SendSelectionChangedEvent(wxEVT_COMBOBOX); // fall through: for compatibility with wxGTK, also send the text // update event when the selection changes (this also seems more // logical as the text does change) case CBN_EDITCHANGE: if ( m_allowTextEvents ) { wxCommandEvent event(wxEVT_TEXT, GetId()); // if sel != -1, value was already initialized above if ( sel == -1 ) { value = wxGetWindowText(GetHwnd()); } event.SetString(value); InitCommandEventWithItems(event, sel); ProcessCommand(event); } break; default: return wxChoice::MSWCommand(param, id); } // skip wxChoice version as it would generate its own events for // CBN_SELENDOK and also interfere with our handling of CBN_DROPDOWN return true; }
bool wxChoice::MSWCommand(WXUINT param, WXWORD WXUNUSED(id)) { /* The native control provides a great variety in the events it sends in the different selection scenarios (undoubtedly for greater amusement of the programmers using it). For the reference, here are the cases when the final selection is accepted (things are quite interesting when it is cancelled too): A. Selecting with just the arrows without opening the dropdown: 1. CBN_SELENDOK 2. CBN_SELCHANGE B. Opening dropdown with F4 and selecting with arrows: 1. CBN_DROPDOWN 2. many CBN_SELCHANGE while changing selection in the list 3. CBN_SELENDOK 4. CBN_CLOSEUP C. Selecting with the mouse: 1. CBN_DROPDOWN -- no intermediate CBN_SELCHANGEs -- 2. CBN_SELENDOK 3. CBN_CLOSEUP 4. CBN_SELCHANGE Admire the different order of messages in all of those cases, it must surely have taken a lot of effort to Microsoft developers to achieve such originality. */ switch ( param ) { case CBN_DROPDOWN: // we use this value both because we don't want to track selection // using CB_GETCURSEL while the dropdown is opened and because we // need to reset the selection back to it if it's eventually // cancelled by user m_lastAcceptedSelection = GetCurrentSelection(); break; case CBN_CLOSEUP: // if the selection was accepted by the user, it should have been // reset to wxID_NONE by CBN_SELENDOK, otherwise the selection was // cancelled and we must restore the old one if ( m_lastAcceptedSelection != wxID_NONE ) { SetSelection(m_lastAcceptedSelection); m_lastAcceptedSelection = wxID_NONE; } break; case CBN_SELENDOK: // reset it to prevent CBN_CLOSEUP from undoing the selection (it's // ok to reset it now as GetCurrentSelection() will now return the // same thing anyhow) m_lastAcceptedSelection = wxID_NONE; { const int n = GetSelection(); wxCommandEvent event(wxEVT_COMMAND_CHOICE_SELECTED, m_windowId); event.SetInt(n); event.SetEventObject(this); if ( n > -1 ) { event.SetString(GetStringSelection()); InitCommandEventWithItems(event, n); } ProcessCommand(event); } break; // don't handle CBN_SELENDCANCEL: just leave m_lastAcceptedSelection // valid and the selection will be undone in CBN_CLOSEUP above // don't handle CBN_SELCHANGE neither, we don't want to generate events // while the dropdown is opened -- but do add it if we ever need this default: return false; } return true; }