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