MFC subwindow and parent window (setparent, setowner) I. Concepts and differences
In Windows, each window object corresponds to a data structure to form a list linked list. The system's window manager uses this list to obtain window information and manage each window. This data structure contains four data used to build a list, namely child, sibling, parent, and owner.
So we can see that there are two relationships between windows: Owner-owned and parent-child. The former is known as the owner/owner relationship, and the latter is called the parent/child relationship. In this text, I name the owner window as the owner window. In other words, when a window has a parent window (parent), it may also be owned by different windows (owner) or have its own child window (child ). In the cwnd class of MFC, the owner window is saved in the m_hwndowner member variable, and the parent window is saved in the m_hparent, but these two values do not necessarily correspond to the values in the window object data structure.
The relationship between Windows determines the external performance of windows. Such as display and destruction.
If the owner field of a window data is not null, it establishes a owner-owned relationship with the window data. The owner relationship determines:
(1) The owned window is always displayed in front of the window that owns it;
(2) When the owner's window is minimized, all the windows it owns will be hidden;
(3) When the owner window is destroyed, all the windows it owns will be destroyed.
It should be noted that hiding the owner window does not affect the visible state of the window it owns. For example, if window a has window B and window B has window C, window B is hidden when window a is minimized, but Window C is still visible.
If the parent field of a window is not null, it establishes a parent-child relationship with the window. The Parent and Child determine:
(1) Position of the window on the screen. The parent window provides a coordinate system used to locate the child window. A child window can only be displayed in the customer area of its parent window, and other parts will be dropped. This cut rule determines that if the parent window is invisible, the Child Window is certainly invisible. If the parent window is moved out of the screen, the Child window is the same.
(2) when the parent window is hidden, all its child windows are also hidden.
(3) when the parent window is destroyed, its child windows will be destroyed.
Note! Minimizing the parent window will not affect the visible status of the Child Window. The child window will be minimized with the parent window, but its ws_visible attribute will not change.
In Windows, why do we need two relationships? This is for a more flexible management window. For example, the drop-down list box (list box) of the ComboBox can be exceeded the customer area of the parent window of the ComboBox, which is conducive to display. Therefore, when the system creates the list box, is a subwindow of the console window (desktop window). Its parent window hwndparent is null. In this way, the display area of list box is limited to the entire screen, however, the owner of the list box is the first non-Child Window ancestor of the combo box (such as the dialog box). When its owner window is destroyed, the list box is automatically destroyed.
In addition, the transmission of messages between windows is also related to the window relationship. Generally, a window sends its own notification message to its parent window, but not all of them, for example, the ctoolbar sends a notification message to its owner window instead of the parent window. In this way, you can allow a toolbar to be used as a subwindow of a window (such as an OLE container program window) and send messages to another window (such as an in-place Framework Window. Microsoft does not explicitly indicate who the message is sent to, whether it is the parent window or the owner window. In addition, when a server window is activated or becomes invalid during in-place editing, the child windows in the Framework Window are automatically hidden or displayed, this is also achieved by directly calling the setowner function.
Ii. Description and restrictions of Window Types
(1) console window (desktop window ). This is the earliest system creation window. It can be considered as the owner and parent windows of all ws_overlapped windows. Kyle marsh pointed out in his article "Win32 window hierarchy and styles" that when the system is initialized, it first creates a console window to overwrite the entire screen. All other windows are displayed on this console window. The first in the window list used by the window manager is the console. The next layer of window is called top-level window. Top-level window refers to all non-child, no parent window, or the parent window is a desktop window. They do not have the ws_child attribute.
(2) ws_overlapped window can be displayed anywhere on the screen. Their owner window is the console.
Overlapped windows are top-level windows, which are generally the main windows of applications. Whether or not the ws_caption and ws_border attributes are provided, such windows have a title bar and border after being created. Overlapped windows can have other top-level windows or other top-level windows. All overlapped windows have the ws_clipsiblings attribute. The system can automatically set the size and initial position of the overlapped window.
When the system shuts down, it will destroy all overlapped windows.
(3) ws_popup window can be displayed anywhere on the screen. Generally, there is no parent window. However, if setparent is called explicitly, this type of window can also have a parent window.
The owner of the ws_popup window is given by setting the hwndparent parameter in the createwindow function. If the hwndparent is not a subwindow, the window becomes the owner of the new pop-up window. Otherwise, the system looks up from the parent window of hwndparent until it finds the first non-Child Window and uses it as the owner of the pop-up window. When the owner window is destroyed, the window is automatically destroyed.
A pop-up window also belongs to a top-level window. The main difference between a pop-up window and an overlapped window is that a pop-up window does not need a title bar or a border. Pop-up can have other top-level windows or be owned. All pop-up windows also have the ws_clipsiblings attribute.
(4) Owner windows can only be overlapped or pop-up windows. subwindows cannot be owner windows, that is, subwindows cannot have other windows.
Overlapped or pop-up windows can be owned when they have other windows.
When creating a ws_overlapped or ws_popup window using createjavaswex, you can give the handle of its owner window in the hwndparent parameter. If hwndparent provides a child-type window handle, the system automatically gives ownership of the newly created window to the top-level parent window of the Child Window. In this case, the hwndparent parameter is saved in the parent domain of the new window, and its owner window handle is saved in the owner domain.
(5) by default, the dialog box and message box belong to the owned window, unless the ws_child attribute is explicitly given during the creation of them (for example, the dialog box is embedded in the dialog box)
Otherwise, the system specifies the owner window for them. Note that once an owned window is created, all its relationships cannot be changed because Win32 does not provide a method to change the window owner.
In Win32, due to multithreading, ensure that the parent and child windows or owner/owned windows belong to the same thread.
(6) For a ws_child window, its parent window is its owner window. The parent window of a Child Window is also specified by the hwndparent parameter in the createwindow function. The child window can only be displayed in the customer area of the parent window and destroyed along with the parent window.
A child window must have a parent window, which is the main difference between it and overlapped and pop-up windows. The parent window can be a top-level window or another child window.
Iii. Description of several related functions
(1) GET/set owner window
Win32 API provides the getwindow function (gw_owner flag) to obtain the owner window handle of a window.
Getwindow (hwnd, gw_owner) always returns the owner of the window ). For child windows, the function returns NULL because their parent windows are equivalent to the owner (note that they are "equivalent "). Because the owner information of the subwindow is not maintained in windows.
In MFC, the owner window pointer is obtained through the following function:
_ Afxwin_inline cwnd * cwnd: getowner () const
{Return m_hwndowner! = NULL? Cwnd: fromhandle (m_hwndowner): getparent ();}
From the code above, we can see that the returned value is different from the value returned by getwindow. If the current window has no owner, its parent window pointer is returned.
However, Windows does not provide a way to change the window owner. In MFC, the following methods are provided to change the owner:
_ Afxwin_inline void cwnd: setowner (cwnd * pownerwnd)
{M_hwndowner = pownerwnd! = NULL? Pownerwnd-> m_hwnd: NULL ;}
In addition, MFC provides the cwnd: getsafeowner (cwnd * pparent, hwnd * pwndtop); function, which can be used to obtain the parent window pointer of the first non-Child attribute of the pparent parameter. If this parameter is null, the main window of the current thread is returned (obtained through afxgetmainwnd ). The framework often uses this function to find the owner window of a dialog box or attribute page.
(2) Obtain/set the parent window
Win32 API provides the getparent and setparent functions. The MFC fully encapsulates these two functions:
_ Afxwin_inline cwnd * cwnd: setparent (cwnd * pwndnewparent)
{Assert (: iswindow (m_hwnd); Return cwnd: fromhandle (: setparent (m_hwnd,
Pwndnewparent-> getsafehwnd ()));}
_ Afxwin_inline cwnd * cwnd: getparent () const
{Assert (: iswindow (m_hwnd); Return cwnd: fromhandle (: getparent (m_hwnd ));}
For setparent, msdn shows that the parent and child windows must be of the same process. However, because the window handle is globally unique in the system and does not belong to the same process, it can also be called successfully, but the consequences are unknown.
The return value of getparent is complex. For overlapped windows, it returns 0. For ws_child windows, it returns its parent window. For ws_popup windows, it returns its owner window, if you want to obtain the hwndparent parameter passed in when creating it, use the getwindowword (gww_hwndparent) function.
(3) getwindowword (hwnd, gww_hwndparent) returns the parent window of a window. If not, it returns its owner.
(4) As mentioned above, when an owner window is minimized, the system automatically hides its own window. When the owner window is restored, the system automatically displays the window it owns. In both cases, the system will send the (send) wm_showwindow message to the owned window. In some cases, we may need to hide the owned window, but do not want to minimize its owner window. At this time, we can use the showownedpopups function, this function sets or deletes the ws_visible attribute of the window owned by the current window, and then sends the wm_showwindow message update window.