diff --git a/docs/changes.txt b/docs/changes.txt index 0f9b9fda2b..c2e57013d0 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -584,7 +584,7 @@ wxGTK: wxMSW: - Compilation fix for WXWIN_COMPATIBILITY_2_6=1 case (Tim Stahlhut). - +- Fix behaviour of wxComboBox using ID=1000. 3.0-RC2: (released 2013-10-28) diff --git a/include/wx/msw/combobox.h b/include/wx/msw/combobox.h index 8649187c09..5fc7cc5cf1 100644 --- a/include/wx/msw/combobox.h +++ b/include/wx/msw/combobox.h @@ -133,6 +133,9 @@ protected: virtual wxSize DoGetSizeFromTextSize(int xlen, int ylen = -1) const; + // Override this one to avoid eating events from our popup listbox. + virtual wxWindow *MSWFindItem(long id, WXHWND hWnd) const; + // this is the implementation of GetEditHWND() which can also be used when // we don't have the edit control, it simply returns NULL then // diff --git a/include/wx/msw/control.h b/include/wx/msw/control.h index 29897ad9c3..35bf74e9fe 100644 --- a/include/wx/msw/control.h +++ b/include/wx/msw/control.h @@ -121,6 +121,9 @@ protected: // one virtual WXHBRUSH DoMSWControlColor(WXHDC pDC, wxColour colBg, WXHWND hWnd); + // Look in our GetSubcontrols() for the windows with the given ID. + virtual wxWindow *MSWFindItem(long id, WXHWND hWnd) const; + // for controls like radiobuttons which are really composite this array // holds the ids (not HWNDs!) of the sub controls wxArrayLong m_subControls; diff --git a/include/wx/msw/window.h b/include/wx/msw/window.h index 3475f3d6b7..bd793e143b 100644 --- a/include/wx/msw/window.h +++ b/include/wx/msw/window.h @@ -206,7 +206,7 @@ public: // to understand why does it work, look at SubclassWin() code and comments bool IsOfStandardClass() const { return m_oldWndProc != NULL; } - wxWindow *FindItem(long id) const; + wxWindow *FindItem(long id, WXHWND hWnd = NULL) const; wxWindow *FindItemByHWND(WXHWND hWnd, bool controlOnly = false) const; // MSW only: true if this control is part of the main control @@ -663,6 +663,15 @@ protected: bool MSWEnableHWND(WXHWND hWnd, bool enable); + // Return the pointer to this window or one of its sub-controls if this ID + // and HWND combination belongs to one of them. + // + // This is used by FindItem() and is overridden in wxControl, see there. + virtual wxWindow* MSWFindItem(long WXUNUSED(id), WXHWND WXUNUSED(hWnd)) const + { + return NULL; + } + private: // common part of all ctors void Init(); diff --git a/src/msw/combobox.cpp b/src/msw/combobox.cpp index cb0885892e..24f187036f 100644 --- a/src/msw/combobox.cpp +++ b/src/msw/combobox.cpp @@ -674,4 +674,22 @@ wxSize wxComboBox::DoGetSizeFromTextSize(int xlen, int ylen) const return tsize; } +wxWindow *wxComboBox::MSWFindItem(long id, WXHWND hWnd) const +{ + // The base class version considers that any window with the same ID as + // this one must be this window itself, but this is not the case for the + // comboboxes where the native control seems to always use the ID of 1000 + // for the popup listbox that it creates -- and this ID may be the same as + // our own one. So we must explicitly check the HWND value too here and + // avoid eating the events from the listbox as otherwise it is rendered + // inoperative, see #15647. + if ( id == GetId() && hWnd != GetHWND() ) + { + // Must be the case described above. + return NULL; + } + + return wxChoice::MSWFindItem(id, hWnd); +} + #endif // wxUSE_COMBOBOX diff --git a/src/msw/control.cpp b/src/msw/control.cpp index 1fe94bab92..4bb6ae8423 100644 --- a/src/msw/control.cpp +++ b/src/msw/control.cpp @@ -442,6 +442,15 @@ WXHBRUSH wxControl::MSWControlColorDisabled(WXHDC pDC) GetHWND()); } +wxWindow* wxControl::MSWFindItem(long id, WXHWND hWnd) const +{ + // is it us or one of our "internal" children? + if ( id == GetId() || (GetSubcontrols().Index(id) != wxNOT_FOUND) ) + return const_cast(this); + + return wxControlBase::MSWFindItem(id, hWnd); +} + // ---------------------------------------------------------------------------- // wxControlWithItems // ---------------------------------------------------------------------------- diff --git a/src/msw/window.cpp b/src/msw/window.cpp index 5fed10ca6c..225e13d531 100644 --- a/src/msw/window.cpp +++ b/src/msw/window.cpp @@ -365,30 +365,21 @@ END_EVENT_TABLE() // --------------------------------------------------------------------------- // Find an item given the MS Windows id -wxWindow *wxWindowMSW::FindItem(long id) const +wxWindow *wxWindowMSW::FindItem(long id, WXHWND hWnd) const { -#if wxUSE_CONTROLS - wxControl *item = wxDynamicCastThis(wxControl); - if ( item ) - { - // is it us or one of our "internal" children? - if ( item->GetId() == id -#ifndef __WXUNIVERSAL__ - || (item->GetSubcontrols().Index(id) != wxNOT_FOUND) -#endif // __WXUNIVERSAL__ - ) - { - return item; - } - } -#endif // wxUSE_CONTROLS + // First check for the control itself and its Windows-level children which + // are mapped to the same wxWindow at wx level. + wxWindow *wnd = MSWFindItem(id, hWnd); + if ( wnd ) + return wnd; + // Then check wx level children. wxWindowList::compatibility_iterator current = GetChildren().GetFirst(); while (current) { wxWindow *childWin = current->GetData(); - wxWindow *wnd = childWin->FindItem(id); + wnd = childWin->FindItem(id, hWnd); if ( wnd ) return wnd; @@ -5324,7 +5315,7 @@ bool wxWindowMSW::HandleCommand(WXWORD id_, WXWORD cmd, WXHWND control) // try the id if ( !win ) { - win = FindItem(id); + win = FindItem(id, control); } if ( win )