Make wxChoice and wxComboBox behaviour same as in native controls in wxMSW.
Keep the item selected from the drop down using keyboard when switching away from the control by pressing TAB: although this generates CBN_SELENDCANCEL notification, the selection is actually kept by the native controls in this case, so don't reset it ourselves -- even though it makes sense, it makes wx applications behave differently from the native ones. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@73103 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -106,7 +106,8 @@ protected:
|
|||||||
// common part of all ctors
|
// common part of all ctors
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
m_lastAcceptedSelection = wxID_NONE;
|
m_lastAcceptedSelection =
|
||||||
|
m_pendingSelection = wxID_NONE;
|
||||||
m_heightOwn = wxDefaultCoord;
|
m_heightOwn = wxDefaultCoord;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,10 +163,13 @@ protected:
|
|||||||
virtual void MSWEndDeferWindowPos();
|
virtual void MSWEndDeferWindowPos();
|
||||||
#endif // wxUSE_DEFERRED_SIZING
|
#endif // wxUSE_DEFERRED_SIZING
|
||||||
|
|
||||||
// last "completed" selection, i.e. not the transient one while the user is
|
// These variables are only used while the drop down is opened.
|
||||||
// browsing the popup list: this is only used when != wxID_NONE which is
|
//
|
||||||
// the case while the drop down is opened
|
// The first one contains the item that had been originally selected before
|
||||||
int m_lastAcceptedSelection;
|
// the drop down was opened and the second one the item we should select
|
||||||
|
// when the drop down is closed again.
|
||||||
|
int m_lastAcceptedSelection,
|
||||||
|
m_pendingSelection;
|
||||||
|
|
||||||
// the height of the control itself if it was set explicitly or
|
// the height of the control itself if it was set explicitly or
|
||||||
// wxDefaultCoord if it hadn't
|
// wxDefaultCoord if it hadn't
|
||||||
|
@@ -740,9 +740,7 @@ bool wxChoice::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
|
|||||||
/*
|
/*
|
||||||
The native control provides a great variety in the events it sends in
|
The native control provides a great variety in the events it sends in
|
||||||
the different selection scenarios (undoubtedly for greater amusement of
|
the different selection scenarios (undoubtedly for greater amusement of
|
||||||
the programmers using it). For the reference, here are the cases when
|
the programmers using it). Here are the different cases:
|
||||||
the final selection is accepted (things are quite interesting when it
|
|
||||||
is cancelled too):
|
|
||||||
|
|
||||||
A. Selecting with just the arrows without opening the dropdown:
|
A. Selecting with just the arrows without opening the dropdown:
|
||||||
1. CBN_SELENDOK
|
1. CBN_SELENDOK
|
||||||
@@ -764,6 +762,12 @@ bool wxChoice::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
|
|||||||
Admire the different order of messages in all of those cases, it must
|
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
|
surely have taken a lot of effort to Microsoft developers to achieve
|
||||||
such originality.
|
such originality.
|
||||||
|
|
||||||
|
Additionally, notice that CBN_SELENDCANCEL doesn't seem to actually
|
||||||
|
cancel anything, if we get CBN_SELCHANGE before it, as it happens in
|
||||||
|
the case (B), the selection is still accepted. This doesn't make much
|
||||||
|
sense and directly contradicts MSDN documentation but is how the native
|
||||||
|
comboboxes behave and so we do the same thing.
|
||||||
*/
|
*/
|
||||||
switch ( param )
|
switch ( param )
|
||||||
{
|
{
|
||||||
@@ -776,31 +780,40 @@ bool wxChoice::MSWCommand(WXUINT param, WXWORD WXUNUSED(id))
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case CBN_CLOSEUP:
|
case CBN_CLOSEUP:
|
||||||
// if the selection was accepted by the user, it should have been
|
if ( m_pendingSelection != wxID_NONE )
|
||||||
// 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);
|
// This can only happen in the case (B), so set the item
|
||||||
m_lastAcceptedSelection = wxID_NONE;
|
// selected in the drop down as our real selection.
|
||||||
|
SendSelectionChangedEvent(wxEVT_COMMAND_CHOICE_SELECTED);
|
||||||
|
m_pendingSelection = wxID_NONE;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CBN_SELENDOK:
|
case CBN_SELENDOK:
|
||||||
// reset it to prevent CBN_CLOSEUP from undoing the selection (it's
|
// Reset the variables to prevent CBN_CLOSEUP from doing anything,
|
||||||
// ok to reset it now as GetCurrentSelection() will now return the
|
// it's not needed if we do get CBN_SELENDOK.
|
||||||
// same thing anyhow)
|
m_lastAcceptedSelection =
|
||||||
m_lastAcceptedSelection = wxID_NONE;
|
m_pendingSelection = wxID_NONE;
|
||||||
|
|
||||||
SendSelectionChangedEvent(wxEVT_COMMAND_CHOICE_SELECTED);
|
SendSelectionChangedEvent(wxEVT_COMMAND_CHOICE_SELECTED);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CBN_SELCHANGE:
|
||||||
|
// If we get this event after CBN_SELENDOK, i.e. cases (A) or (C)
|
||||||
|
// above, we don't have anything to do. But in the case (B) we need
|
||||||
|
// to remember that the selection should really change once the
|
||||||
|
// drop down is closed.
|
||||||
|
if ( m_lastAcceptedSelection != wxID_NONE )
|
||||||
|
m_pendingSelection = GetCurrentSelection();
|
||||||
|
break;
|
||||||
|
|
||||||
// don't handle CBN_SELENDCANCEL: just leave m_lastAcceptedSelection
|
case CBN_SELENDCANCEL:
|
||||||
// valid and the selection will be undone in CBN_CLOSEUP above
|
// Do not reset m_pendingSelection here -- it would make sense but,
|
||||||
|
// as described above, native controls keep the selection even when
|
||||||
// don't handle CBN_SELCHANGE neither, we don't want to generate events
|
// closing the drop down by pressing Escape or TAB, so conform to
|
||||||
// while the dropdown is opened -- but do add it if we ever need this
|
// their behaviour.
|
||||||
|
m_lastAcceptedSelection = wxID_NONE;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@@ -274,26 +274,27 @@ bool wxComboBox::MSWCommand(WXUINT param, WXWORD id)
|
|||||||
case CBN_DROPDOWN:
|
case CBN_DROPDOWN:
|
||||||
// remember the last selection, just as wxChoice does
|
// remember the last selection, just as wxChoice does
|
||||||
m_lastAcceptedSelection = GetCurrentSelection();
|
m_lastAcceptedSelection = GetCurrentSelection();
|
||||||
if ( m_lastAcceptedSelection == -1 )
|
|
||||||
{
|
|
||||||
// but unlike with wxChoice we may have no selection but still
|
|
||||||
// have some text and we should avoid erasing it if the drop
|
|
||||||
// down is cancelled (see #8474)
|
|
||||||
m_lastAcceptedSelection = wxID_NONE;
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_DROPDOWN, GetId());
|
wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_DROPDOWN, GetId());
|
||||||
event.SetEventObject(this);
|
event.SetEventObject(this);
|
||||||
ProcessCommand(event);
|
ProcessCommand(event);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CBN_CLOSEUP:
|
case CBN_CLOSEUP:
|
||||||
|
// Do the same thing as in wxChoice but using different event type.
|
||||||
|
if ( m_pendingSelection != wxID_NONE )
|
||||||
|
{
|
||||||
|
SendSelectionChangedEvent(wxEVT_COMMAND_COMBOBOX_SELECTED);
|
||||||
|
m_pendingSelection = wxID_NONE;
|
||||||
|
}
|
||||||
{
|
{
|
||||||
wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_CLOSEUP, GetId());
|
wxCommandEvent event(wxEVT_COMMAND_COMBOBOX_CLOSEUP, GetId());
|
||||||
event.SetEventObject(this);
|
event.SetEventObject(this);
|
||||||
ProcessCommand(event);
|
ProcessCommand(event);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CBN_SELENDOK:
|
case CBN_SELENDOK:
|
||||||
#ifndef __SMARTPHONE__
|
#ifndef __SMARTPHONE__
|
||||||
// we need to reset this to prevent the selection from being undone
|
// we need to reset this to prevent the selection from being undone
|
||||||
|
Reference in New Issue
Block a user