Search code examples
c++dependency-injectionwxwidgets

How to terminate wxWidgets message loop without destroying main frame?


I am beginer to wxWidgets. I have problem with standard way of terminating application by calling Destroy() in MyFrame::OnClose() event handler :

In MyApp::OnInit() i am creating MyFrame with constructor parameter loaded from configuration file (use of dependency injection). This parameter is stored inside MyFrame and can change during lifetime of MyFrame.

When application exits i need to MyApp::OnExit() gets this parameter from MyFrame and saves it. So MyFrame must still exist in MyApp::OnExit().

I dont like to save this parameter in MyFrame::OnClose() because i dont want to MyFrame be dependent on configuration file functions - thats job of application class at higher level.

I think if i am creating something, for example MyFrame in OnInit() then perfect place to destroy it is OnExit() right? So, exist some correct way to delay destroying of MyFrame to MyApp::OnExit() ?

myapp.cpp :

#include <wx/wx.h>
#include "myframe.h"

class MyApp : public wxApp {
public:
    virtual bool OnInit() override;
    virtual int  OnExit() override;
    MyFrame* m_myframe;
};


IMPLEMENT_APP( MyApp );

extern int  LoadSettings();
extern void SaveSettings( int param );

bool MyApp::OnInit()
{
    const int param = LoadSettings();
    m_myframe = new MyFrame( "MyFrame title", param );
    m_myframe->SetIcon( wxICON(aaaa) );
    m_myframe->Show();
    return true;
}

int MyApp::OnExit()
{
    const int param = m_myframe->GetParameter();
    SaveSettings( param );
    m_myframe->Destroy();
    return 0;
}

myframe.h:

#include <wx/wx.h>

class MyFrame: public wxFrame {
public:
    MyFrame( const wxString& title, int param );
    int GetParameter() const { return m_param; }
    /* ... */
private:
    void OnClose( wxCloseEvent& event );
    int m_param;
};

myframe.cpp :

#include "myframe.h"

MyFrame::MyFrame( const wxString& title, int param )
:   wxFrame( nullptr, -1, title ),
    m_param( param )
{
    Bind( wxEVT_CLOSE_WINDOW, &MyFrame::OnClose, this );
}

void MyFrame::OnClose( wxCloseEvent &event )
{
    // Want to terminate message loop but without destroying this
    // Destroy();
}

Solution

  • Perhaps in MyFrame::OnClose() you can have it emit a boost::signal notifying subscribers that it is about to be destroyed? You will then, of course, set up a method in MyApp to be invoked when this signal is emitted and have this method save that parameter.

    On a slightly related note, I used to always do something similar whenever a wxFrame-derived object was destroyed. That is, I would have it save some information to persistent storage before it was destroyed. The way I handled this was to simply use wxConfig. I would get a handle to the global wxConfig object in the wxEVT_CLOSE_WINDOW handler method and then save what I needed saved from there.

    To me, this was a cleaner design. An object should be responsible for saving itself to persistent storage. Having another object A (in your case, your MyApp object) being responsible for saving the state of object B means that object A will always need to be kept up to date as to what things of object B needs to be saved. IMO, it's much better for object A to say to object B "hey, save your self" and then let object B handle the details.