X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2fd284a4a09793c29078296529d3e9db5acd0a0f..380a5dd80316202b472967e898feba1386ea5345:/docs/latex/wx/tdelwin.tex?ds=inline diff --git a/docs/latex/wx/tdelwin.tex b/docs/latex/wx/tdelwin.tex index 33e368dd68..da562d0c26 100644 --- a/docs/latex/wx/tdelwin.tex +++ b/docs/latex/wx/tdelwin.tex @@ -3,48 +3,56 @@ Classes: \helpref{wxCloseEvent}{wxcloseevent}, \helpref{wxWindow}{wxwindow} Window deletion can be a confusing subject, so this overview is provided -to make it clear when and how you delete windows, or respond to user requests +to help make it clear when and how you delete windows, or respond to user requests to close windows. \wxheading{What is the sequence of events in a window deletion?} When the user clicks on the system close button or system close command, -in a frame or a dialog, wxWindows calls \helpref{wxWindow::Close}{wxwindowclose}. +in a frame or a dialog, wxWidgets calls \helpref{wxWindow::Close}{wxwindowclose}. This +in turn generates an EVT\_CLOSE event: see \helpref{wxCloseEvent}{wxcloseevent}. -This function then generates a \helpref{wxCloseEvent}{wxcloseevent} event which -can be handled by the application (by using an EVT\_CLOSE event table entry). It is the duty of the application to -define a suitable event handler, and decide whether or not to destroy the window. -If the application is for some reason forcing the application to close, -the window should always be destroyed, otherwise there is the option to +It is the duty of the application to define a suitable event handler, and +decide whether or not to destroy the window. +If the application is for some reason forcing the application to close +(\helpref{wxCloseEvent::CanVeto}{wxcloseeventcanveto} returns false), the window should always be destroyed, otherwise there is the option to ignore the request, or maybe wait until the user has answered a question -before deciding whether it's safe to close. +before deciding whether it is safe to close. The handler for EVT\_CLOSE should +signal to the calling code if it does not destroy the window, by calling +\helpref{wxCloseEvent::Veto}{wxcloseeventveto}. Calling this provides useful information +to the calling code. The wxCloseEvent handler should only call \helpref{wxWindow::Destroy}{wxwindowdestroy} to delete the window, and not use the {\bf delete} operator. This is because -for some window classes, wxWindows delays actual deletion of the window until all events have been processed, +for some window classes, wxWidgets delays actual deletion of the window until all events have been processed, since otherwise there is the danger that events will be sent to a non-existent window. +As reinforced in the next section, calling Close does not guarantee that the window +will be destroyed. Call \helpref{wxWindow::Destroy}{wxwindowdestroy} if you want to be +certain that the window is destroyed. + \wxheading{How can the application close a window itself?} -Your application can use the \helpref{wxWindow::Close}{wxwindowclose} event just as -the framework does. Pass a TRUE argument to this function to tell the event handler -that we definitely want to delete the frame. +Your application can either use \helpref{wxWindow::Close}{wxwindowclose} event just as +the framework does, or it can call \helpref{wxWindow::Destroy}{wxwindowdestroy} directly. +If using Close(), you can pass a true argument to this function to tell the event handler +that we definitely want to delete the frame and it cannot be vetoed. -If for some reason you don't wish to use the {\bf Close} function to delete a window, at least use -the {\bf Destroy} function so that wxWindows can decide when it's safe to delete the window. +The advantage of using Close instead of Destroy is that it will call any clean-up code +defined by the EVT\_CLOSE handler; for example it may close a document contained in +a window after first asking the user whether the work should be saved. Close can be vetoed +by this process (return false), whereas Destroy definitely destroys the window. \wxheading{What is the default behaviour?} -By default, the close event handlers for wxFrame and wxDialog -both call the old \helpref{wxWindow::OnClose}{wxwindowonclose} handler -for backward compatibility. So you can still use the old form if you wish. - -In addition, the default close event handler for wxDialog simulates a Cancel command, +The default close event handler for wxDialog simulates a Cancel command, generating a wxID\_CANCEL event. Since the handler for this cancel event might -itself call {\bf Close}, there is a check for infinite looping. +itself call {\bf Close}, there is a check for infinite looping. The default handler +for wxID\_CANCEL hides the dialog (if modeless) or calls EndModal(wxID\_CANCEL) (if modal). +In other words, by default, the dialog {\it is not destroyed} (it might have been created +on the stack, so the assumption of dynamic creation cannot be made). -Under Windows, wxDialog also defines a handler for \helpref{wxWindow::OnCharHook}{wxwindowoncharhook} that -generates a Cancel event if the Escape key has been pressed. +The default close event handler for wxFrame destroys the frame using Destroy(). \wxheading{What should I do when the user calls up Exit from a menu?} @@ -59,13 +67,10 @@ the exit command altogether. \wxheading{What should I do to upgrade my 1.xx OnClose to 2.0?} -In wxWindows 1.xx, the {\bf OnClose} function did not actually delete 'this', but signalled -to the calling function (either {\bf Close}, or the wxWindows framework) to delete +In wxWidgets 1.xx, the {\bf OnClose} function did not actually delete 'this', but signaled +to the calling function (either {\bf Close}, or the wxWidgets framework) to delete or not delete the window. -You can still use this function unchanged in 2.0, but it's worth upgrading to -the new method in case future versions of wxWindows does not support the old one. - To update your code, you should provide an event table entry in your frame or dialog, using the EVT\_CLOSE macro. The event handler function might look like this: @@ -73,22 +78,13 @@ dialog, using the EVT\_CLOSE macro. The event handler function might look like t \begin{verbatim} void MyFrame::OnCloseWindow(wxCloseEvent& event) { - // If the application forces the deletion, - // obey without question. - if (event.GetForce()) - { - this->Destroy(); - return; - } - - // Otherwise... if (MyDataHasBeenModified()) { wxMessageDialog* dialog = new wxMessageDialog(this, "Save changed data?", "My app", wxYES_NO|wxCANCEL); int ans = dialog->ShowModal(); - dialog->Close(TRUE); + dialog->Destroy(); switch (ans) { @@ -101,6 +97,10 @@ dialog, using the EVT\_CLOSE macro. The event handler function might look like t break; case wxID_CANCEL: // Do nothing - so don't quit app. default: + if (!event.CanVeto()) // Test if we can veto this deletion + this->Destroy(); // If not, destroy the window anyway. + else + event.Veto(); // Notify the calling code that we didn't delete the frame. break; } } @@ -110,8 +110,10 @@ dialog, using the EVT\_CLOSE macro. The event handler function might look like t \wxheading{How do I exit the application gracefully?} -A wxWindows application automatically exits when the designated top window, or the -last frame or dialog, is destroyed. +A wxWidgets application automatically exits when the last top level window +(\helpref{wxFrame}{wxframe} or \helpref{wxDialog}{wxdialog}), is destroyed. Put +any application-wide cleanup code in \helpref{wxApp::OnExit}{wxapponexit} (this +is a virtual function, not an event handler). \wxheading{Do child windows get deleted automatically?}