Reputation: 45
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
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