Unlike the modal dialog box, the non-modal dialog box does not monopolize user input. After you open the non-modal dialog box, you can still interact with other interfaces.
The design of the non-modal dialog box is similar to that of the modal dialog box. It also includes two parts: the Design dialog box template and the design cdialog class derived class. However, during the creation and deletion of the dialog box, the non-Modal Dialog Box differs from the modal dialog box in the following ways:
The template of the non-modal dialog box must have the visible style; otherwise, the dialog box is invisible, and the modal dialog box does not need to set the style. The more insurance method is to call cwnd: showwindow (sw_show) to display the dialog box, regardless of whether the dialog box has the visible style.
The non-Modal Dialog Box objects are dynamically created using the new operator in the heap, instead of being embedded into other objects in the form of member variables or built on the stack in the form of local variables. Generally, a pointer member variable pointing to the dialog box class should be declared in the dialog box owner's window class, through which the dialog box object can be accessed.
Call the cdialog: Create Function to start the dialog box, instead of cdialog: domodal. This is the key to the modal dialog box. Since the create function does not start a new message loop, the dialog box and the application share the same message loop, so that the dialog box will not monopolize user input. Create returns the result immediately after the dialog box is displayed, while domodal returns the result only after the dialog box is closed. As we all know, in the MFC program, the lifetime of the window object should be longer than the corresponding window, that is, the corresponding window object cannot be deleted without closing the window on the screen. After the return result of create, you cannot determine whether the dialog box is closed or not, so you cannot determine the lifetime of the dialog box object. Therefore, you have to build the dialog box object in the heap, it cannot be constructed in the form of local variables.
You must call cwnd: destroywindow instead of cdialog: enddialog to close the non-modal dialog box. Calling cwnd: destroywindow is a common method for directly deleting a window. Because the default cdialog: onok and cdialog: oncancel functions call enddialog, the programmer must write their own onok and oncancel functions and call destroywindow in the function to close the dialog box.
Because the non-Modal Dialog Box object is built using the new operator, you must use the delete operator to delete the dialog box object after the dialog box is closed. After a window is deleted on the screen, the Framework calls cwnd: postncdestroy, which is a virtual function. The program can delete window objects in this function. The Code is as follows:
Void cmodelessdialog: postncdestroy
{
Delete this; // Delete the object itself
}
In this way, after the dialog box is deleted, the dialog box objects are automatically deleted. The owner object does not need to explicitly call Delete to delete the dialog box objects.
There must be a flag indicating whether the non-modal dialog box is open. The reason for this is that you may choose to open the command again when opening a modal dialog box. The program determines whether to open a new dialog box or simply activate the original Dialog Box Based on the flag. Generally, the pointer to the dialog box object in the owner window can be used as this flag. When the dialog box is closed, a null value is assigned to the pointer to indicate that the dialog box object does not exist.
Tip: In C ++ programming, a common method to determine whether an object in the heap exists is to determine whether the pointer to this object is null. This mechanism requires the programmer to initialize the pointer to the object to a null value, assign the returned address to the pointer when creating the object, and set the pointer to a null value when deleting the object. |
Based on the above analysis, we can easily change the login data dialog box in the register program to a non-modal dialog box. The advantage of this is that if you find that an error data exists in the editing view when entering the data, you do not have to close the dialog box and modify it in the editing view.
Follow these steps:
On the more styles page of the template Properties dialog box in the log on data dialog box, select visible.
Add the cregisterview class definition in the registerview. h header file
Public:
Cregisterdialog * m_pregisterdlg;
Add the cregisterdialog class declaration to the header file of registerview. h.
Class cregisterdialog;
The reason for adding this row is that there is a cregisterdialog type pointer in the cregisterview class. Therefore, you must ensure that the cregisterdialog class declaration appears before cregisterview. Otherwise, errors will occur during compilation. There are two ways to solve this problem, one is to ensure that the # include "registerview. H "statement before # include" registerdialog. h "statement, this method creates a dependency, increases the compilation burden, not very good; another method is to add a cregisterdialog statement before the cregisterview class declaration to temporarily "blind" the compiler, so that there is # include "registerview. in the module of the H Statement, unless the cregisterdialog class is used, # include "registerdialog. H Statement.
Add the following two lines at the end of the # include statement area in the header of the registerdialog. cpp File
# Include "registerdoc. H"
# Include "registerview. H"
Use classwizard to add oncancel and postncdestroy member functions to the cregisterdialog class. The method is to enter classwizard, select the message maps page, and select cregisterdialog in the class name column. Then, select idcancel in the object IDs column, and double-click bn_clicked in the messages column to create oncancel. To create postncdestroy, first select cregisterdialog in the object IDs column, and then double-click postncdestroy in the messages column.
Modify the cregisterview class and the cregisterdialog class by listing 5.10 and 5.11 respectively.
Listing 5.10 code of the cregisterview class
Cregisterview: cregisterview ()
{
// Todo: Add construction code here
M_pregisterdlg = NULL; // pointer Initialization is null
}
Void cregisterview: oneditregister ()
{
// Todo: add your command handler code here
If (m_pregisterdlg)
M_pregisterdlg-> setactivewindow (); // activation dialog box
Else
{
// Create a non-Modal Dialog Box
M_pregisterdlg = new cregisterdialog (this );
M_pregisterdlg-> Create (idd_register, this );
}
}
Listing 5.11 code of cregisterdialog
Void cregisterdialog: postncdestroy ()
{
// Todo: add your specialized code here and/or call the base class
Delete this; // delete a dialog box object
}
Void cregisterdialog: oncancel ()
{
// Todo: add extra cleanup here
(Cregisterview *) m_pparent)-> m_pregisterdlg = NULL;
Destroywindow (); // Delete dialog box
}
Cregisterview: The oneditregister function determines whether the logon data dialog box has been opened. If yes, activate the dialog box. Otherwise, create the dialog box. This function mainly calls the following functions:
Call the cwnd: setactivewindow activation dialog box. The function declaration is
Cwnd * setactivewindow ();
This function makes this window an activity window and returns the window of the original activity.
Call cdialog: Create to display the dialog box. The declaration of this function is
Bool create (uint nidtemplate, cwnd * pparentwnd = NULL );
The nidtemplate parameter is the ID of the dialog box template. Pparentwnd specifies the parent window or owner of the dialog box.
After you click "cancel" in the login data dialog box, cregisterdialog: oncancel will be called and cwnd: destroywindow will be called in this function to close the dialog box, set m_pregisterdlg of the cregisterview member to null to indicate that the dialog box is closed. The call to destroywindow causes the call to cregisterdialog: postncdestroy. In this function, the delete operator is used to delete the cregisterdialog object.
Compile and run register. Now the login data dialog box has become a non-modal dialog box.
5.4.2 automatic clearing of window objects
An MFC window object contains two elements: one is the window object encapsulation window, that is, the hwnd (window handle) stored in the m_hwnd member ), second, the window object itself is a C ++ object. To delete an MFC window object, delete the window object encapsulated by the window object and then delete the window object itself.
The most direct method to delete a window is to call cwnd: destroywindow or: destroywindow. The former encapsulates the latter's functions. The former not only calls the latter, but also invalidates the hwnd saved by m_hwnd (null ). If destroywindow deletes a parent window or owner window, the function automatically deletes all child windows or owner windows before deleting the parent window or owner. In general, you do not need to directly call destroywindow in the program to delete the window, because MFC will automatically call destroywindow to delete the window. For example, when a user exits the application, a wm_close message is generated, which causes the MFC to automatically call cwnd: destroywindow to delete the main framework window, when you press the OK or cancel button in the dialog box, MFC automatically calls cwnd: destroywindow to delete the dialog box and its controls.
The deletion of window objects is divided into two types based on the object creation method. In MFC programming, a large number of window objects are used. Some window objects are embedded in another object as variables or created on the stack as local variables, some are created in the heap using the new operator. For a window object created as a variable, the programmer does not have to worry about its deletion, because the life cycle of the object is always limited. if the object is a member variable of an object, it disappears as the parent object disappears. if the object is a local variable, it is cleared when the function returns.
The lifetime of a window object dynamically created in the heap is arbitrary. When beginners are learning C ++ programming, they are often not very practical about the use of the new operator. Because New is used to create an object in the heap, they cannot forget to delete the object with Delete. When learning the MFC routine, the reader may have such a question: why does some programs use new to create a window object without explicitly using Delete to delete it? The answer is that some MFC window objects can be automatically cleared.
As mentioned earlier in the non-modal dialog box, when you call cwnd: destroywindow or: destroywindow to delete a window, the postncdestroy member function of the deleted window will be called. The default postncdestroy does nothing, but some MFC window classes will overwrite the function and call Delete this in the new version of postncdestroy to delete the object, thus providing the automatic clearing function. This type of window objects are usually created in the heap with the new operator, but the programmer does not have to worry about using the delete operator to delete them, because once the destroywindow is called to delete the window, the corresponding window object will be deleted immediately.
The window classes that do not have the automatic clearing function are as follows. These window objects are usually created in the form of variables, without the need to automatically clear the function.
All standard Windows Control classes.
Subwindow objects derived directly from the cwnd class (such as custom controls ).
Split Window class csplitterwnd.
The default control bar class (including the toolbar, Status Bar, and dialog bar ).
Modal Dialog Box class.
The window classes with the automatic clearing function are as follows. These window objects are usually created in the heap.
Main framework window class (derived directly or indirectly from the cframewnd class ).
View class (derived directly or indirectly from the cview class ).
When designing your own derived window class, you can decide whether to design the window class to be automatically cleared Based on the window object creation method. For example, for a non-modal dialog box, the object is created in the heap, so it should have the automatic clearing function.
To sum up, for the MFC window class and its derived class, you do not need to explicitly Delete the window object in the program. That is to say, you do not need to call destroywindow to delete the window encapsulated by the window object, or use the delete operator explicitly to delete the window object itself. As long as the non-automatically cleared window objects are created in the form of variables, the automatically cleared window objects are created in the heap, And the MFC operating mechanism can ensure that the window objects are completely deleted.
To manually delete a window object, call the corresponding function (such as cwnd: destroywindow) to delete the window and then delete the window object. window objects created in the form of variables are automatically deleted by the framework. for non-automatically cleared window objects dynamically created in the heap, after the window is deleted, delete is called explicitly to delete objects (usually in the destructor of the owner or parent window ). for window objects with the automatic clearing function, you only need to call cwnd: destroywindow to delete the window objects and window objects. Note: Do not use the delete operator to delete window objects created in the heap before the window is closed.