From 6ba93d23bfc6a5764ff7fcc751d9b6164c23e10e Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Wed, 17 Aug 2005 13:30:33 +0000 Subject: [PATCH] made wxChoice and wxComboBox::GetSelection() return only completed selection in wxMSW; added GetCurrentSelection() with the old behaviour and documented it git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@35211 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/changes.txt | 2 ++ docs/latex/wx/choice.tex | 22 +++++++++++++++ include/wx/msw/choice.h | 18 +++++++++++- src/msw/choice.cpp | 60 ++++++++++++++++++++++++++++------------ src/msw/combobox.cpp | 10 +++++-- 5 files changed, 91 insertions(+), 21 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 1b00eddd20..0b08751062 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -19,6 +19,8 @@ All: All (GUI): - Added wxStaticText::Wrap() +- wxChoice and wxComboBox::GetSelection() now returns completed selection, + added a new GetCurrentSelection() function having the old behaviour - Added wxXmlResource::Unload(). - Possibility of modeless wxWizard dialog (with presentation in sample). - Fixed a rare crash due to malformed HTML in wxHTML (Xavier Nodet). diff --git a/docs/latex/wx/choice.tex b/docs/latex/wx/choice.tex index 7ef251b085..f810c735a0 100644 --- a/docs/latex/wx/choice.tex +++ b/docs/latex/wx/choice.tex @@ -37,6 +37,7 @@ when an item on the list is selected.} \latexignore{\rtfignore{\wxheading{Members}}} + \membersection{wxChoice::wxChoice}\label{wxchoicector} \func{}{wxChoice}{\void} @@ -87,12 +88,14 @@ a list of strings.} \perlnote{In wxPerl there is just an array reference in place of {\tt n} and {\tt choices}.} + \membersection{wxChoice::\destruct{wxChoice}}\label{wxchoicedtor} \func{}{\destruct{wxChoice}}{\void} Destructor, destroying the choice item. + \membersection{wxChoice::Create}\label{wxchoicecreate} \func{bool}{Create}{\param{wxWindow *}{parent}, \param{wxWindowID}{ id},\rtfsp @@ -109,6 +112,7 @@ Destructor, destroying the choice item. Creates the choice for two-step construction. See \helpref{wxChoice::wxChoice}{wxchoicector}. + \membersection{wxChoice::Delete}\label{wxchoicedelete} \func{void}{Delete}{\param{int }{n}} @@ -119,6 +123,7 @@ Deletes the item with the given index from the control. \docparam{n}{The item to delete.} + \membersection{wxChoice::GetColumns}\label{wxchoicegetcolumns} \constfunc{int}{GetColumns}{\void} @@ -130,6 +135,23 @@ Gets the number of columns in this choice item. This is implemented for Motif only and always returns $1$ for the other platforms. + +\membersection{wxChoice::GetCurrentSelection}\label{wxchoicegetcurrentselection} + +\constfunc{int}{GetCurrentSelection}{\void} + +Unlike \helpref{GetSelection}{wxcontrolwithitemsgetselection} which only +returns the accepted selection value, i.e. the selection in the control once +the user closes the dropdown list, this function returns the current selection. +That is, while the dropdown list is shown, it returns the currently selected +item in it. When it is not shown, its result is the same as for the other +function. + +\newsince{2.6.2} (before this version +\helpref{GetSelection}{wxcontrolwithitemsgetselection} itself behaved like +this). + + \membersection{wxChoice::SetColumns}\label{wxchoicesetcolumns} \func{void}{SetColumns}{\param{int}{ n = 1}} diff --git a/include/wx/msw/choice.h b/include/wx/msw/choice.h index 5667010c9a..4661025fe9 100644 --- a/include/wx/msw/choice.h +++ b/include/wx/msw/choice.h @@ -24,7 +24,7 @@ class WXDLLEXPORT wxChoice : public wxChoiceBase { public: // ctors - wxChoice() { } + wxChoice() { Init(); } virtual ~wxChoice(); wxChoice(wxWindow *parent, @@ -36,8 +36,10 @@ public: const wxValidator& validator = wxDefaultValidator, const wxString& name = wxChoiceNameStr) { + Init(); Create(parent, id, pos, size, n, choices, style, validator, name); } + wxChoice(wxWindow *parent, wxWindowID id, const wxPoint& pos, @@ -47,6 +49,7 @@ public: const wxValidator& validator = wxDefaultValidator, const wxString& name = wxChoiceNameStr) { + Init(); Create(parent, id, pos, size, choices, style, validator, name); } @@ -75,6 +78,9 @@ public: virtual int GetCount() const; virtual int GetSelection() const; +#if wxABI_VERSION >= 20602 + virtual int GetCurrentSelection() const; +#endif virtual void SetSelection(int n); virtual int FindString(const wxString& s) const; @@ -87,6 +93,9 @@ public: virtual WXHBRUSH MSWControlColor(WXHDC hDC, WXHWND hWnd); protected: + // common part of all ctors + void Init() { m_lastAcceptedSelection = wxID_NONE; } + virtual void DoMoveWindow(int x, int y, int width, int height); virtual void DoSetItemClientData( int n, void* clientData ); virtual void* DoGetItemClientData( int n ) const; @@ -120,6 +129,13 @@ protected: // free all memory we have (used by Clear() and dtor) void Free(); + + // last "completed" selection, i.e. not the transient one while the user is + // browsing the popup list: this is only used when != wxID_NONE which is + // the case while the drop down is opened + int m_lastAcceptedSelection; + + DECLARE_DYNAMIC_CLASS_NO_COPY(wxChoice) }; diff --git a/src/msw/choice.cpp b/src/msw/choice.cpp index 859e700b71..31b0b5f46c 100644 --- a/src/msw/choice.cpp +++ b/src/msw/choice.cpp @@ -306,6 +306,17 @@ void wxChoice::Free() // ---------------------------------------------------------------------------- int wxChoice::GetSelection() const +{ + // if m_lastAcceptedSelection is set, it means that the dropdown is + // currently shown and that we want to use the last "permanent" selection + // instead of whatever is under the mouse pointer currently + // + // otherwise, get the selection from the control + return m_lastAcceptedSelection == wxID_NONE ? GetCurrentSelection() + : m_lastAcceptedSelection; +} + +int wxChoice::GetCurrentSelection() const { return (int)SendMessage(GetHwnd(), CB_GETCURSEL, 0, 0); } @@ -621,27 +632,42 @@ WXLRESULT wxChoice::MSWWindowProc(WXUINT nMsg, WXWPARAM wParam, WXLPARAM lParam) bool wxChoice::MSWCommand(WXUINT param, WXWORD WXUNUSED(id)) { - if ( param != CBN_SELCHANGE) + switch ( param ) { - // "selection changed" is the only event we're after - return false; - } + case CBN_DROPDOWN: + // we don't want to track selection using CB_GETCURSEL while the + // dropdown is opened + m_lastAcceptedSelection = GetCurrentSelection(); + break; - int n = GetSelection(); - if (n > -1) - { - wxCommandEvent event(wxEVT_COMMAND_CHOICE_SELECTED, m_windowId); - event.SetInt(n); - event.SetEventObject(this); - event.SetString(GetStringSelection()); - if ( HasClientObjectData() ) - event.SetClientObject( GetClientObject(n) ); - else if ( HasClientUntypedData() ) - event.SetClientData( GetClientData(n) ); - ProcessCommand(event); + case CBN_CLOSEUP: + // it should be safe to use CB_GETCURSEL again + m_lastAcceptedSelection = wxID_NONE; + break; + + case CBN_SELCHANGE: + { + const int n = GetSelection(); + + wxCommandEvent event(wxEVT_COMMAND_CHOICE_SELECTED, m_windowId); + event.SetInt(n); + event.SetEventObject(this); + + if ( n > -1 ) + { + event.SetString(GetStringSelection()); + if ( HasClientObjectData() ) + event.SetClientObject( GetClientObject(n) ); + else if ( HasClientUntypedData() ) + event.SetClientData( GetClientData(n) ); + } + + ProcessCommand(event); + } + return true; } - return true; + return false; } WXHBRUSH wxChoice::MSWControlColor(WXHDC hDC, WXHWND hWnd) diff --git a/src/msw/combobox.cpp b/src/msw/combobox.cpp index e61f41c12b..ca8e3d4af2 100644 --- a/src/msw/combobox.cpp +++ b/src/msw/combobox.cpp @@ -328,7 +328,7 @@ bool wxComboBox::MSWProcessEditMsg(WXUINT msg, WXWPARAM wParam, WXLPARAM lParam) return false; } -bool wxComboBox::MSWCommand(WXUINT param, WXWORD WXUNUSED(id)) +bool wxComboBox::MSWCommand(WXUINT param, WXWORD id) { wxString value; int sel = -1; @@ -398,10 +398,14 @@ bool wxComboBox::MSWCommand(WXUINT param, WXWORD WXUNUSED(id)) ProcessCommand(event); } break; + + default: + return wxChoice::MSWCommand(param, id); } - // there is no return value for the CBN_ notifications, so always return - // false from here to pass the message to DefWindowProc() + // let the def window proc have it by returning false, but do not pass the + // message we've already handled here (notably CBN_SELCHANGE) to the base + // class as it would generate another event for them return false; } -- 2.45.2