giorgio_developer
giorgio_developer

Reputation: 45

Close event not invoked in wxWindow

I'm creating a program that can have multiple files open simultaneously (using a wxAuiNotebook). I'm trying to create a system that warns the user whenever he tries to close a window with unsaved data, but the close event doesn't seem to get invoked.

TimelineWindow::TimelineWindow(wxWindow* parent, TimelineData* data) 
    : wxScrolledWindow(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxALWAYS_SHOW_SB)
{
    SetData(data);
    Bind(wxEVT_CLOSE_WINDOW, &TimelineWindow::OnClose, this);
}

void TimelineWindow::OnClose(wxCloseEvent& event)
{
    if (event.CanVeto() && data->IsDirty()) // Dunno what this does, but the wiki tells me to use this
    {
        int choice = wxMessageBox("Save changes?",
            "Unsaved changes", wxICON_QUESTION | wxYES_NO | wxCANCEL, this);

        switch (choice)
        {
            // Save changes and close
        case wxYES:

            break;

            // Close without saving changes
        case wxNO:

            break;

            // Don't close
        case wxCANCEL:

            break;
        }

        event.Veto();
    }

    event.Skip();
}

I've also tried binding the event through DECLARE_EVENT_TABLE(), which also didn't work. I guess this event doesn't work with wxScrolledWindow's or wxWindow's in general? Is there any way to make it work?

Also, I need to make it so if the user presses wxCANCEL, the window closing process is cancelled. Is this possible?

Upvotes: 0

Views: 406

Answers (1)

VZ.
VZ.

Reputation: 22678

wxEVT_CLOSE_WINDOW is only sent to top level windows, so you need to bind to it there and not in TimelineWindow which looks like a child window. This makes sense, if you think about it, because only top level windows can really be closed by the user -- all the other windows can only be destroyed ("closed" is the word used for TLWs only) by the program itself, so it doesn't need an event to know about when it happens. And if you really need to do something when a window is destroyed, just do it in the usual way, by doing it in its destructor. Of course, you can't veto destroying the window by then, but then you shouldn't have to, because different parts of your program are not supposed to fight with each other!

You can prevent the window from being closed in your handler by vetoing it, i.e. calling event.Veto(), as you already do -- except you should only do it if the user answers that they don't want to close, not always.

Finally, consider using wxMessageDialog::SetYesNoCancelLabels() to make the choices in the dialog more clear to the user.

Upvotes: 1

Related Questions