diff --git a/docs/changes.txt b/docs/changes.txt index 9ece7eb97e..ad02856376 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -380,6 +380,7 @@ wxMSW: - Fix drawing owner-drawn menu items with bitmaps (Jacob Gillespie, #23230). - Improve ScrollTo() with wxDV_VARIABLE_LINE_HEIGHT (Jens Göpfert, #23102). - Fix libraries names in Arch64 CMake build (Tobias Taschner, #23347). +- Fix using wxComboCtrl with AUI floating pane as parent (#23399). wxOSX: diff --git a/include/wx/combo.h b/include/wx/combo.h index 727c26ecb9..e44a72b86d 100644 --- a/include/wx/combo.h +++ b/include/wx/combo.h @@ -455,6 +455,9 @@ public: // common code to be called on popup hide/dismiss void OnPopupDismiss(bool generateEvent); + // called if popup is destroyed not by wxComboCtrl itself + void OnPopupDestroy(); + // PopupShown states enum { diff --git a/src/common/combocmn.cpp b/src/common/combocmn.cpp index 80408c6677..98f1d584c9 100644 --- a/src/common/combocmn.cpp +++ b/src/common/combocmn.cpp @@ -351,6 +351,46 @@ protected: virtual void OnDismiss() wxOVERRIDE; #endif +#ifdef __WXMSW__ + virtual bool MSWHandleMessage(WXLRESULT *result, + WXUINT message, + WXWPARAM wParam, + WXLPARAM lParam) wxOVERRIDE + { + // This is a workaround for a MSW-specific problem: popup windows are + // created with the TLW and not the combobox itself as their parent and + // so if the TLW gets destroyed, they're destroyed together with it, + // but the associated wxComboCtrl may survive if it gets reparented to + // something else, which is exactly what happens when it's used inside + // a wxAUI pane. And if this wxComboCtrl is opened again later, it + // tries to use the existing popup whose HWND had been destroyed, which + // doesn't work at all. + // + // To prevent this from happening, we delete the popup if this happens + // to force recreating it later. + if ( message == WM_DESTROY && !m_isBeingDeleted ) + { + m_combo->OnPopupDestroy(); + + // We can't delete it immediately because this object is used after + // this function returns, so do it slightly later. + wxWindow* const self = this; + m_combo->CallAfter([self]() + { + // Before really deleting it, reset the HWND which had been + // already destroyed, to prevent us from trying to destroy it + // again (which would just fail with an error). + self->DissociateHandle(); + + delete self; + }); + } + + return wxComboPopupWindowBase::MSWHandleMessage(result, message, + wParam, lParam); + } +#endif // __WXMSW__ + private: // This is the same as our parent, but has the right type, so that we can // avoid using casts later. @@ -2367,6 +2407,14 @@ void wxComboCtrlBase::HidePopup(bool generateEvent) OnPopupDismiss(generateEvent); } +void wxComboCtrlBase::OnPopupDestroy() +{ + m_winPopup = NULL; + + delete m_popupInterface; + m_popupInterface = NULL; +} + // ---------------------------------------------------------------------------- // customization methods // ---------------------------------------------------------------------------- diff --git a/src/generic/odcombo.cpp b/src/generic/odcombo.cpp index 4651b7ebf8..7131ba5fe6 100644 --- a/src/generic/odcombo.cpp +++ b/src/generic/odcombo.cpp @@ -990,7 +990,6 @@ void wxOwnerDrawnComboBox::DoSetPopupControl(wxComboPopup* popup) if ( !GetVListBoxComboPopup()->GetCount() ) { GetVListBoxComboPopup()->Populate(m_initChs); - m_initChs.Clear(); } }