diff --git a/include/wx/aui/framemanager.h b/include/wx/aui/framemanager.h index fa3b98dabd..f910101346 100644 --- a/include/wx/aui/framemanager.h +++ b/include/wx/aui/framemanager.h @@ -555,6 +555,7 @@ public: protected: // protected events + void OnDestroy(wxWindowDestroyEvent& evt); void OnPaint(wxPaintEvent& evt); void OnEraseBackground(wxEraseEvent& evt); void OnSize(wxSizeEvent& evt); diff --git a/interface/wx/aui/framemanager.h b/interface/wx/aui/framemanager.h index 14c05fe6d5..7f25e9e12f 100644 --- a/interface/wx/aui/framemanager.h +++ b/interface/wx/aui/framemanager.h @@ -484,11 +484,12 @@ public: void StartPaneDrag(wxWindow* paneWindow, const wxPoint& offset); /** - Uninitializes the framework and should be called before a managed frame or - window is destroyed. UnInit() is usually called in the managed wxFrame's - destructor. It is necessary to call this function before the managed frame - or window is destroyed, otherwise the manager cannot remove its custom event - handlers from a window. + Dissociate the managed window from the manager. + + This function may be called before the managed frame or window is + destroyed, but, since wxWidgets 3.1.4, it's unnecessary to call it + explicitly, as it will be called automatically when this window is + destroyed, as well as when the manager itself is. */ void UnInit(); diff --git a/samples/aui/auidemo.cpp b/samples/aui/auidemo.cpp index 492f0ba61b..008a26427a 100644 --- a/samples/aui/auidemo.cpp +++ b/samples/aui/auidemo.cpp @@ -116,8 +116,6 @@ public: const wxSize& size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE | wxSUNKEN_BORDER); - ~MyFrame(); - wxAuiDockArt* GetDockArt(); void DoUpdate(); @@ -1016,11 +1014,6 @@ MyFrame::MyFrame(wxWindow* parent, m_mgr.Update(); } -MyFrame::~MyFrame() -{ - m_mgr.UnInit(); -} - wxAuiDockArt* MyFrame::GetDockArt() { return m_mgr.GetArtProvider(); diff --git a/src/aui/framemanager.cpp b/src/aui/framemanager.cpp index dda8873922..e9aed4e5f0 100644 --- a/src/aui/framemanager.cpp +++ b/src/aui/framemanager.cpp @@ -593,6 +593,7 @@ bool wxAuiPaneInfo::IsValid() const wxBEGIN_EVENT_TABLE(wxAuiManager, wxEvtHandler) EVT_AUI_PANE_BUTTON(wxAuiManager::OnPaneButton) EVT_AUI_RENDER(wxAuiManager::OnRender) + EVT_WINDOW_DESTROY(wxAuiManager::OnDestroy) EVT_PAINT(wxAuiManager::OnPaint) EVT_ERASE_BACKGROUND(wxAuiManager::OnEraseBackground) EVT_SIZE(wxAuiManager::OnSize) @@ -632,6 +633,8 @@ wxAuiManager::wxAuiManager(wxWindow* managed_wnd, unsigned int flags) wxAuiManager::~wxAuiManager() { + UnInit(); + // NOTE: It's possible that the windows have already been destroyed by the // time this dtor is called, so this loop can result in memory access via // invalid pointers, resulting in a crash. So it will be disabled while @@ -914,6 +917,8 @@ void wxAuiManager::SetManagedWindow(wxWindow* wnd) { wxASSERT_MSG(wnd, wxT("specified window must be non-NULL")); + UnInit(); + m_frame = wnd; m_frame->PushEventHandler(this); @@ -950,14 +955,16 @@ void wxAuiManager::SetManagedWindow(wxWindow* wnd) } -// UnInit() must be called, usually in the destructor -// of the frame class. If it is not called, usually this -// will result in a crash upon program exit +// UnInit() is called automatically by wxAuiManager itself when either the +// manager itself or its associated frame is destroyed, but can also be called +// explicitly, so make it safe to call it multiple times and just do nothing +// during any calls but the first one. void wxAuiManager::UnInit() { if (m_frame) { m_frame->RemoveEventHandler(this); + m_frame = NULL; } } @@ -3951,6 +3958,12 @@ void wxAuiManager::Repaint(wxDC* dc) delete client_dc; } +void wxAuiManager::OnDestroy(wxWindowDestroyEvent& event) +{ + if ( event.GetEventObject() == m_frame ) + UnInit(); +} + void wxAuiManager::OnPaint(wxPaintEvent& WXUNUSED(event)) { wxPaintDC dc(m_frame);