Fix text input and completion in wxComboCtrl and wxOwnerDrawnComboBox.

Both wxEVT_KEY_DOWN and wxEVT_CHAR must be handled and only the latter
used for completion (or any characters input). Don't make incorrect
assumptions about wxEVT_CHAR keycodes either, it's only the Unicode
character and printability that matter.

Otherwise, completion in readonly controls wouldn't work correctly
for e.g. numbers on numpad or non-ASCII characters.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@63864 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Václav Slavík 2010-04-05 17:19:04 +00:00
parent 10265e6c41
commit c765e6fb9d
4 changed files with 81 additions and 31 deletions

View File

@ -523,6 +523,7 @@ protected:
void OnTextCtrlEvent(wxCommandEvent& event);
void OnSysColourChanged(wxSysColourChangedEvent& event);
void OnKeyEvent(wxKeyEvent& event);
void OnCharEvent(wxKeyEvent& event);
// Set customization flags (directs how wxComboCtrlBase helpers behave)
void Customize( wxUint32 flags ) { m_iFlags |= flags; }
@ -726,10 +727,14 @@ public:
// Default implementation draws value as string.
virtual void PaintComboControl( wxDC& dc, const wxRect& rect );
// Receives key events from the parent wxComboCtrl.
// Receives wxEVT_KEY_DOWN key events from the parent wxComboCtrl.
// Events not handled should be skipped, as usual.
virtual void OnComboKeyEvent( wxKeyEvent& event );
// Receives wxEVT_CHAR key events from the parent wxComboCtrl.
// Events not handled should be skipped, as usual.
virtual void OnComboCharEvent( wxKeyEvent& event );
// Implement if you need to support special action when user
// double-clicks on the parent wxComboCtrl.
virtual void OnComboDoubleClick();

View File

@ -89,6 +89,7 @@ public:
virtual wxSize GetAdjustedSize( int minWidth, int prefHeight, int maxHeight );
virtual void PaintComboControl( wxDC& dc, const wxRect& rect );
virtual void OnComboKeyEvent( wxKeyEvent& event );
virtual void OnComboCharEvent( wxKeyEvent& event );
virtual void OnComboDoubleClick();
virtual bool LazyCreate();
@ -117,8 +118,8 @@ public:
protected:
// Called by OnComboDoubleClick and OnComboKeyEvent
bool HandleKey( int keycode, bool saturate, wxChar unicode = 0 );
// Called by OnComboDoubleClick and OnCombo{Key,Char}Event
bool HandleKey( int keycode, bool saturate, wxChar keychar = 0 );
// sends combobox select event from the parent combo control
void SendComboBoxEvent( int selection );
@ -164,6 +165,7 @@ protected:
void OnMouseMove(wxMouseEvent& event);
void OnMouseWheel(wxMouseEvent& event);
void OnKey(wxKeyEvent& event);
void OnChar(wxKeyEvent& event);
void OnLeftClick(wxMouseEvent& event);
// Return the widest item width (recalculating it if necessary)

View File

@ -465,6 +465,7 @@ private:
BEGIN_EVENT_TABLE(wxComboPopupWindowEvtHandler, wxEvtHandler)
EVT_KEY_DOWN(wxComboPopupWindowEvtHandler::OnKeyEvent)
EVT_KEY_UP(wxComboPopupWindowEvtHandler::OnKeyEvent)
EVT_CHAR(wxComboPopupWindowEvtHandler::OnKeyEvent)
#if USES_GENERICTLW
EVT_ACTIVATE(wxComboPopupWindowEvtHandler::OnActivate)
#endif
@ -552,6 +553,11 @@ void wxComboPopup::OnComboKeyEvent( wxKeyEvent& event )
event.Skip();
}
void wxComboPopup::OnComboCharEvent( wxKeyEvent& event )
{
event.Skip();
}
void wxComboPopup::OnComboDoubleClick()
{
}
@ -780,6 +786,7 @@ BEGIN_EVENT_TABLE(wxComboCtrlBase, wxControl)
EVT_IDLE(wxComboCtrlBase::OnIdleEvent)
//EVT_BUTTON(wxID_ANY,wxComboCtrlBase::OnButtonClickEvent)
EVT_KEY_DOWN(wxComboCtrlBase::OnKeyEvent)
EVT_CHAR(wxComboCtrlBase::OnCharEvent)
EVT_TEXT_ENTER(wxID_ANY,wxComboCtrlBase::OnTextCtrlEvent)
EVT_SYS_COLOUR_CHANGED(wxComboCtrlBase::OnSysColourChanged)
END_EVENT_TABLE()
@ -1830,6 +1837,27 @@ void wxComboCtrlBase::OnKeyEvent(wxKeyEvent& event)
}
}
void wxComboCtrlBase::OnCharEvent(wxKeyEvent& event)
{
if ( IsPopupShown() )
{
// pass it to the popped up control
GetPopupControl()->GetControl()->GetEventHandler()->ProcessEvent(event);
}
else // no popup
{
wxComboPopup* popupInterface = GetPopupControl();
if ( popupInterface )
{
popupInterface->OnComboCharEvent(event);
}
else
{
event.Skip();
}
}
}
void wxComboCtrlBase::OnFocusEvent( wxFocusEvent& event )
{
if ( event.GetEventType() == wxEVT_SET_FOCUS )

View File

@ -54,6 +54,7 @@
BEGIN_EVENT_TABLE(wxVListBoxComboPopup, wxVListBox)
EVT_MOTION(wxVListBoxComboPopup::OnMouseMove)
EVT_KEY_DOWN(wxVListBoxComboPopup::OnKey)
EVT_CHAR(wxVListBoxComboPopup::OnChar)
EVT_LEFT_UP(wxVListBoxComboPopup::OnLeftClick)
END_EVENT_TABLE()
@ -244,7 +245,7 @@ void wxVListBoxComboPopup::SendComboBoxEvent( int selection )
}
// returns true if key was consumed
bool wxVListBoxComboPopup::HandleKey( int keycode, bool saturate, wxChar unicode )
bool wxVListBoxComboPopup::HandleKey( int keycode, bool saturate, wxChar keychar )
{
const int itemCount = GetCount();
@ -256,19 +257,12 @@ bool wxVListBoxComboPopup::HandleKey( int keycode, bool saturate, wxChar unicode
int value = m_value;
int comboStyle = m_combo->GetWindowStyle();
// this is the character equivalent of the code
wxChar keychar = 0;
if ( keycode < WXK_START )
if ( keychar > 0 )
{
if ( unicode > 0 )
{
if ( wxIsprint(unicode) )
keychar = unicode;
}
else if ( wxIsprint(keycode) )
{
keychar = (wxChar) keycode;
}
// we have character equivalent of the keycode; filter out these that
// are not printable characters
if ( !wxIsprint(keychar) )
keychar = 0;
}
if ( keycode == WXK_DOWN || keycode == WXK_NUMPAD_DOWN || keycode == WXK_RIGHT )
@ -395,13 +389,21 @@ void wxVListBoxComboPopup::OnComboDoubleClick()
void wxVListBoxComboPopup::OnComboKeyEvent( wxKeyEvent& event )
{
// Saturated key movement on
if ( !HandleKey(event.GetKeyCode(),true,
if ( !HandleKey(event.GetKeyCode(), true) )
event.Skip();
}
void wxVListBoxComboPopup::OnComboCharEvent( wxKeyEvent& event )
{
// unlike in OnComboKeyEvent, wxEVT_CHAR contains meaningful
// printable character information, so pass it
#if wxUSE_UNICODE
event.GetUnicodeKey()
const wxChar charcode = event.GetUnicodeKey();
#else
0
const wxChar charcode = (wxChar)event.GetKeyCode();
#endif
) )
if ( !HandleKey(event.GetKeyCode(), true, charcode) )
event.Skip();
}
@ -466,20 +468,33 @@ void wxVListBoxComboPopup::OnKey(wxKeyEvent& event)
}
else
{
int comboStyle = m_combo->GetWindowStyle();
int keycode = event.GetKeyCode();
// Process partial completion key codes here, but not the arrow keys as the base class will do that for us
if ((comboStyle & wxCB_READONLY) &&
(keycode >= WXK_SPACE) && (keycode <=255) && (keycode != WXK_DELETE) && wxIsprint(keycode))
{
OnComboKeyEvent(event);
SetSelection(m_value); // ensure the highlight bar moves
}
else
event.Skip();
// completion is handled in OnChar() below
event.Skip();
}
}
void wxVListBoxComboPopup::OnChar(wxKeyEvent& event)
{
if ( m_combo->GetWindowStyle() & wxCB_READONLY )
{
// Process partial completion key codes here, but not the arrow keys as
// the base class will do that for us
#if wxUSE_UNICODE
const wxChar charcode = event.GetUnicodeKey();
#else
const wxChar charcode = (wxChar)event.GetKeyCode();
#endif
if ( wxIsprint(charcode) )
{
OnComboCharEvent(event);
SetSelection(m_value); // ensure the highlight bar moves
return; // don't skip the event
}
}
event.Skip();
}
void wxVListBoxComboPopup::Insert( const wxString& item, int pos )
{
// Need to change selection?