]>
Commit | Line | Data |
---|---|---|
a660d684 KB |
1 | \section{Window deletion overview}\label{windowdeletionoverview} |
2 | ||
3 | Classes: \helpref{wxCloseEvent}{wxcloseevent}, \helpref{wxWindow}{wxwindow} | |
4 | ||
5 | Window deletion can be a confusing subject, so this overview is provided | |
6 | to make it clear when and how you delete windows, or respond to user requests | |
7 | to close windows. | |
8 | ||
9 | \wxheading{What is the sequence of events in a window deletion?} | |
10 | ||
11 | When the user clicks on the system close button or system close command, | |
e3065973 JS |
12 | in a frame or a dialog, wxWindows calls \helpref{wxWindow::Close}{wxwindowclose}. This |
13 | in turn generates an EVT\_CLOSE event: see \helpref{wxWindow::OnCloseWindow}{wxwindowonclosewindow}. | |
a660d684 | 14 | |
e3065973 JS |
15 | It is the duty of the application to define a suitable event handler, and |
16 | decide whether or not to destroy the window. | |
17 | If the application is for some reason forcing the application to close | |
18 | (\helpref{wxCloseEvent::CanVeto}{wxcloseeventcanveto} returns FALSE), the window should always be destroyed, otherwise there is the option to | |
a660d684 | 19 | ignore the request, or maybe wait until the user has answered a question |
e3065973 JS |
20 | before deciding whether it's safe to close. The handler for EVT\_CLOSE should |
21 | signal to the calling code if it does not destroy the window, by calling | |
22 | \helpref{wxCloseEvent::Veto}{wxcloseeventveto}. Calling this provides useful information | |
23 | to the calling code. | |
a660d684 KB |
24 | |
25 | The wxCloseEvent handler should only call \helpref{wxWindow::Destroy}{wxwindowdestroy} to | |
26 | delete the window, and not use the {\bf delete} operator. This is because | |
27 | for some window classes, wxWindows delays actual deletion of the window until all events have been processed, | |
28 | since otherwise there is the danger that events will be sent to a non-existent window. | |
29 | ||
30 | \wxheading{How can the application close a window itself?} | |
31 | ||
e3065973 JS |
32 | Your application can either use \helpref{wxWindow::Close}{wxwindowclose} event just as |
33 | the framework does, or it can call \helpref{wxWindow::Destroy}{wxwindowdestroy} directly. | |
34 | If using Close(), you can pass a TRUE argument to this function to tell the event handler | |
35 | that we definitely want to delete the frame and it cannot be vetoed. | |
a660d684 | 36 | |
e3065973 JS |
37 | The advantage of using Close instead of Destroy is that it will call any clean-up code |
38 | defined by the EVT\_CLOSE handler; for example it may close a document contained in | |
39 | a window after first asking the user whether the work should be saved. Close can be vetoed | |
40 | by this process (return FALSE), whereas Destroy definitely destroys the window. | |
a660d684 KB |
41 | |
42 | \wxheading{What is the default behaviour?} | |
43 | ||
e3065973 | 44 | The default close event handler for wxDialog simulates a Cancel command, |
a660d684 | 45 | generating a wxID\_CANCEL event. Since the handler for this cancel event might |
e3065973 JS |
46 | itself call {\bf Close}, there is a check for infinite looping. The default handler |
47 | for wxID\_CANCEL hides the dialog (if modeless) or calls EndModal(wxID\_CANCEL) (if modal). | |
48 | In other words, by default, the dialog is not destroyed (it might have been created | |
49 | on the stack, so the assumption of dynamic creation cannot be made). | |
50 | ||
51 | The default close event handler for wxFrame destroys the frame using Destroy(). | |
a660d684 | 52 | |
e3065973 | 53 | Under Windows, wxDialog defines a handler for \helpref{wxWindow::OnCharHook}{wxwindowoncharhook} that |
a660d684 KB |
54 | generates a Cancel event if the Escape key has been pressed. |
55 | ||
56 | \wxheading{What should I do when the user calls up Exit from a menu?} | |
57 | ||
58 | You can simply call \helpref{wxWindow::Close}{wxwindowclose} on the frame. This | |
59 | will invoke your own close event handler which may destroy the frame. | |
60 | ||
61 | You can do checking to see if your application can be safely exited at this point, | |
62 | either from within your close event handler, or from within your exit menu command | |
63 | handler. For example, you may wish to check that all files have been saved. | |
64 | Give the user a chance to save and quit, to not save but quit anyway, or to cancel | |
65 | the exit command altogether. | |
66 | ||
67 | \wxheading{What should I do to upgrade my 1.xx OnClose to 2.0?} | |
68 | ||
69 | In wxWindows 1.xx, the {\bf OnClose} function did not actually delete 'this', but signalled | |
70 | to the calling function (either {\bf Close}, or the wxWindows framework) to delete | |
71 | or not delete the window. | |
72 | ||
a660d684 KB |
73 | To update your code, you should provide an event table entry in your frame or |
74 | dialog, using the EVT\_CLOSE macro. The event handler function might look like this: | |
75 | ||
76 | {\small% | |
77 | \begin{verbatim} | |
78 | void MyFrame::OnCloseWindow(wxCloseEvent& event) | |
79 | { | |
a660d684 KB |
80 | if (MyDataHasBeenModified()) |
81 | { | |
82 | wxMessageDialog* dialog = new wxMessageDialog(this, | |
83 | "Save changed data?", "My app", wxYES_NO|wxCANCEL); | |
84 | ||
85 | int ans = dialog->ShowModal(); | |
e3065973 | 86 | dialog->Destroy(); |
a660d684 KB |
87 | |
88 | switch (ans) | |
89 | { | |
90 | case wxID_YES: // Save, then destroy, quitting app | |
91 | SaveMyData(); | |
92 | this->Destroy(); | |
93 | break; | |
94 | case wxID_NO: // Don't save; just destroy, quitting app | |
95 | this->Destroy(); | |
96 | break; | |
97 | case wxID_CANCEL: // Do nothing - so don't quit app. | |
98 | default: | |
e3065973 JS |
99 | if (!event.CanVeto()) // Test if we can veto this deletion |
100 | this->Destroy(); // If not, destroy the window anyway. | |
101 | else | |
102 | event.Veto(); // Notify the calling code that we didn't delete the frame. | |
a660d684 KB |
103 | break; |
104 | } | |
105 | } | |
106 | } | |
107 | \end{verbatim} | |
108 | }% | |
109 | ||
110 | \wxheading{How do I exit the application gracefully?} | |
111 | ||
2fd284a4 | 112 | A wxWindows application automatically exits when the designated top window, or the |
e3065973 JS |
113 | last frame or dialog, is destroyed. Put any application-wide cleanup code in \helpref{wxApp::OnExit}{wxapponexit} (this |
114 | is a virtual function, not an event handler). | |
a660d684 KB |
115 | |
116 | \wxheading{Do child windows get deleted automatically?} | |
117 | ||
118 | Yes, child windows are deleted from within the parent destructor. This includes any children | |
119 | that are themselves frames or dialogs, so you may wish to close these child frame or dialog windows | |
120 | explicitly from within the parent close handler. | |
121 | ||
122 | \wxheading{What about other kinds of window?} | |
123 | ||
124 | So far we've been talking about `managed' windows, i.e. frames and dialogs. Windows | |
125 | with parents, such as controls, don't have delayed destruction and don't usually have | |
126 | close event handlers, though you can implement them if you wish. For consistency, | |
127 | continue to use the \helpref{wxWindow::Destroy}{wxwindowdestroy} function instead | |
128 | of the {\bf delete} operator when deleting these kinds of windows explicitly. | |
129 |