|
As in all C++ programming, you will create objects either on the stack, or on the heap using new. An object created on the stack is only available until it goes out of scope, at which time its destructor is called and it no longer exists. An object created on the heap, on the other hand, will stay around until either it is explicitly deleted using the delete operator or the program exits. Creating and Deleting Window ObjectsAs a general rule, you will create window objects such as wxFrame and wxButton on the heap using new. Window objects normally have to exist for an indeterminate amount of timethat is, until the user decides the window will be closed. Note that wxWidgets will destroy child objects automatically when the parent is destroyed. Thus, you don't have to destroy a dialog's controls explicitly: just delete the dialog with Destroy. Similarly, upon deletion, a frame automatically deletes any children contained within it. However, if you create a top-level window (such as a frame) as a child of another top-level window (such as another frame), the parent frame does not destroy the child frame. An exception to this is MDI (Multiple Document Interface), where the child frames are not independent windows and are therefore destroyed by the parent. You can create dialogs on the stack, but they must be modal dialogs: call ShowModal to enter an event loop so that all required interaction can happen before the dialog object goes out of scope and is deleted. The mechanics of closing and deleting frames and dialogs can be a source of confusion. To destroy a frame or modeless dialog, the application should use Destroy, which delays deletion until the event queue is empty to avoid events being sent to non-existent windows. However, for a modal dialog, EndModal should first be called to exit the event loop. Event handlers (for example, for an OK button) should not normally destroy the dialog because if the modal dialog is created on the stack, it will be destroyed twice: once by the event handler, and again when the dialog object goes out of scope. When the user closes a modal dialog, the wxEVT_CLOSE_WINDOW event is triggered, and the corresponding event handler should call EndModal (but should not destroy the dialog). The default "close" behavior when clicking on the close button in the title bar is to emulate a wxID_CANCEL command event, whose handler will normally close the dialog. The dialog is then deleted when it goes out of scope. This is how standard dialogs such as wxFileDialog and wxColourDialog work, allowing you to retrieve values from the dialog object when the event loop returns. You can design modal dialogs that destroy the dialog from event handlers, but then you will not be able to create such a dialog on the stack or retrieve values from the dialog object when the user has dismissed it. Here are two ways of using a wxMessageDialog. // 1) Creating the dialog on the stack: no explicit destruction wxMessageDialog dialog(NULL, _("Press OK"), _("App"), wxOK|wxCANCEL); if (dialog.ShowModal() == wxID_OK) { // 2) Creating the dialog on the heap: must delete with Destroy() wxMessageDialog* dialog = new wxMessageDialog(NULL, _("Thank you! "), _("App"), wxOK); dialog->ShowModal(); dialog->Destroy(); } Modeless dialogs and frames will usually need to destroy themselves when closed, either from a control or from the standard window close button or menu. They cannot be created on the stack because they would immediately go out of scope and be destroyed. If you maintain pointers to windows, be sure to reset them to NULL when the corresponding windows have been destroyed. Code to reset the pointer can be written in the window destructor or close handler. For example: void MyFindReplaceDialog::OnCloseWindow(wxCloseEvent& event) { wxGetApp().SetFindReplaceDialog(NULL); Destroy(); } Creating and Copying Drawing ObjectsDrawing objects, such as wxBrush, wxPen, wxColour, wxBitmap, and wxImage, can be created on the stack or on the heap. Drawing code will often create such temporary objects on the stack. These objects are reference-counted, which means that you can use these objects (not pointers to them) with very little overhead: when you assign a brush object to another brush variable, only a reference to the internal data is copied, not all the data itself. This behavior can have slightly unexpected side effects, though, when altering one object also alters another. To avoid such an association between objects, create the copy using a suitable constructor and explicitly assign the properties of the source object to the copy. Here are some examples of reference-counted and "genuine" copying. // Reference-counted copy wxBitmap newBitmap = oldBitmap; // Genuine copy wxBitmap newBitmap = oldBitmap.GetSubBitmap( wxRect(0, 0, oldBitmap.GetWidth(), oldBitmap.GetHeight())); // Reference-counted copy wxFont newFont = oldFont; // Genuine copy wxFont newFont(oldFont.GetPointSize(), oldFont.GetFamily(), oldFont.GetStyle(), oldFont.GetWeight(), oldFont.GetUnderlined(), oldFont.GetFaceName()); Initializing Your Application ObjectBecause your application object may be created before wxWidgets has initialized all its internal objects, such as its color database and default fonts, take care not to rely on such wxWidgets objects within your application constructor. Instead, let these data members take a default value in the constructor and initialize them in OnInit. For example: MyApp::MyApp() { // Do not set at this point // m_font = *wxNORMAL_FONT; } bool MyApp::OnInit() { m_font = *wxNORMAL_FONT; ... return true; } Cleaning Up Your ApplicationYou can override wxApp::OnExit and place much of your cleanup code here. This function is called after all application windows have been destroyed but just before wxWidgets cleans up its own objects. However, some cleanup may need to be done in your main window's close handler, such as killing a process that might try to write to a window. |
|