Kirix Support Forums

UnInit()

Please post all general questions, comments, bug reports, and any other wxAUI feedback here.

UnInit()

Postby 280Z28 on Sat Jan 07, 2006 7:09 pm

Here's what I did, and it worked reliably without crashing for the test app. Let me know what you think.

Code: Select all
// wxAuiFrameManager declaration
public:
    // No need to call UnInit anymore
    //void UnInit();
private:
    void ConnectEventHandler();
    void DisconnectEventHandler();
    void OnWindowClose(wxCloseEvent& event);
    bool m_connected;

// wxAuiFrameManager implementation
BEGIN_EVENT_TABLE(wxAuiFrameManager, wxEvtHandler)
    // ...
    EVT_CLOSE(wxAuiFrameManager::OnWindowClose)
END_EVENT_TABLE()

void wxAuiFrameManager::SetFrame(wxFrame* frame)
{
    // ...
    m_frame = frame;
    //m_frame->PushEventHandler(this); // now handled by ConnectEventHandler()
    ConnectEventHandler();
    // ...
}

void wxAuiFrameManager::ConnectEventHandler()
{
    if ( !m_connected && m_frame )
    {
        m_connected = true;
        m_frame->PushEventHandler(this);
    }
}

// Disconnect is automatically called when the frame wxAUI is managing is closing.
void wxAuiFrameManager::DisconnectEventHandler()
{
    if ( m_connected && m_frame )
        m_frame->PopEventHandler();
    m_connected = false;
}

void wxAuiFrameManager::OnWindowClose(wxCloseEvent& event)
{
    if ( event.GetEventObject() == m_frame )
    {
        // Disconnecting messes up the event processing chain so we can't just Skip().
        // We duplicate the event here and send a new copy down the adjusted chain.
        DisconnectEventHandler();
        wxCloseEvent evt(event);
        m_frame->ProcessEvent(evt);
    }
    else
    {
        event.Skip();
    }
}

280Z28
Registered User
 
Posts: 12
Joined: Sun Jan 01, 2006 10:16 pm
Location: Austin, TX > *

Postby Ben on Sun Jan 08, 2006 1:34 am

Looks great. I would love to try it out and then apply it. I assume it's under the wxWindows license?

All the best,
Ben
User avatar
Ben
Kirix Support Team
 
Posts: 522
Joined: Mon Dec 19, 2005 6:29 am

Postby 280Z28 on Sun Jan 08, 2006 6:37 am

Sure go ahead :)
280Z28
Registered User
 
Posts: 12
Joined: Sun Jan 01, 2006 10:16 pm
Location: Austin, TX > *

Postby Ben on Tue Jan 10, 2006 11:47 am

It turns out that this isn't a good idea. Sometimes a frame can be destroyed by simply calling the wxFrame::Destroy() method, which adds the frame to wx's wxPendingDelete array.

This basically means that a frame can be destroyed without a wxCloseEvent being fired, which means that the UnInit code will not be called, resulting in a crash.

There is a way to do this, but it is tricky and not very clean. You can intercept all frame destructions by adding an OnIdle handler and then monitoring the wxPendingDelete array. Since top level windows have the first crack at examining this array, you can then call UnInit() and disconnect the handler before wx really destroys the frame. As I said, not very clean.

I tried this out, and it worked, but common wisdom says that it is better to be thorough and just require calling UnInit() for now. Maybe in the future I'll add the technique above.
User avatar
Ben
Kirix Support Team
 
Posts: 522
Joined: Mon Dec 19, 2005 6:29 am

Postby mandrav on Tue Jan 10, 2006 1:05 pm

Also consider the case where an app (ab)uses Push/PopEventHandler().
IMHO, calling UnInit() is no big deal and gives more freedom to the app...
mandrav
Registered User
 
Posts: 6
Joined: Sat Jan 07, 2006 2:31 pm
Location: Athens, Greece

Return to wxAUI Questions, Thoughts & Feedback