Click here to Skip to main content
13,350,861 members (56,559 online)
Click here to Skip to main content
Add your own
alternative version


39 bookmarked
Posted 9 Jun 2000

Center CMDIChildWnds and Other Tips

, 6 Apr 2005
Rate this:
Please Sign up or sign in to vote.
Center CMDIChildWnds in the client area of the main frame window.

Sample Image - CenterMDIWnd1.jpg


Have you ever wondered how to get the MDI Child Frame windows in your MDI application to appear centered in the client area of the main frame window? Have you tried using CenterWindow(), but found that the window still isn't centered properly? This article shows you how, and we also talk about the ways of keeping child windows centered, even if the user moves or resizes the main window, or shows or hides the toolbar(s) and status bar.

For the code below, I will assume you are familiar with MFC Doc/View architecture and are using the said architecture in your app. The starter project for the sample application included with this article was created using Visual C++ 6 and the MFC AppWizard. The code in this article has been tested on Windows 98 all editions and Windows NT, 2000, and XP both Home and Professional.

If you have any questions, please feel free to post a message below or email me (see the sample program for the email address). Now, on to centering windows!

The Proper Way to Call CenterWindow()

In this article, we will look more carefully at CenterWindow() and ensure it's called properly. Many thanks go out to the posters to this article's message board (below) for the update. The key to using CenterWindow() is to ensure that the CWnd* pointer you're passing in is the correct pointer, and that the CenterWindow() function is called for the proper window (view, frame, MDI child window etc.) that you mean to center.

Assuming you're using MFC's doc/view architecture, you override CView::OnInitialUpdate and put in the code shown below in bold:

Listing 1: Override of CView::OnInitialUpdate

void CCenterMDIWndView::OnInitialUpdate() 
    // Call base class first


Remember, this code should go in the view enclosed in the frame you want to center. So we see that we call CMDIChildWnd::CenterWindow (which is inherited from CWnd) and pass a pointer to the main frame window of the application, as returned by AfxGetMainWnd(). Thanks go out to Ravi Bhavnani and Michael Zhao for pointing out this simple solution.

Keeping Your Windows Centered

But what about when you want to keep your newly-centered child window centered, say, if the user re-sizes the main frame window or moves the child window outside the client area? Or if the main frame window is minimized and maximized? We need to handle the so-called 'MFC private message', WM_SIZEPARENT. WM_SIZEPARENT is a so-called 'user message,' and it's defined in <afxpriv.h>. The framework sends this message to child windows of the main frame window in response to the main frame window being resized (and hence receiving a WM_SIZE message from Windows).

So I came up with the following algorithm to handle the case of the main frame window being moved or sized by the user (the WM_SIZE message is sent by Windows in both cases):

Figure 2: Algorithm to re-center child windows when user resizes or moves the main frame window of the application.

Let's work from the end of the flowchart up to the handling of the WM_SIZE message. Working this way, my first step is to add a handler to my CChildFrame (derived from CMDIChildWnd) class for the WM_SIZEPARENT message. The code for this message is declared in <afxpriv.h>, so the best policy is to add a #include line for it to STDAFX.H:

Listing 2: Including the Header for WM_SIZEPARENT

#include <afxpriv.h>          // MFC private messages

Next, we have to add a line in the DECLARE_MESSAGE_MAP section of the CHILDFRM.H file (where my CChildFrame class is declared):

Listing 3: The Message Map Declaration in CHILDFRM.H

// Generated message map functions
        // NOTE - the ClassWizard will add and remove member functions here.
        //    DO NOT EDIT what you see in these blocks of generated code!
    afx_msg LRESULT OnSizeParent(WPARAM wParam, LPARAM lParam);

Next we'll go to the CHILDFRM.CPP file and add a message map entry and handler for the WM_SIZEPARENT message. Notice that the code you type is in bold, and we have to add the entire handler implementation from scratch:

Listing 4: Adding a Message Map Entry and Handler Implementation

        // NOTE - the ClassWizard will add and remove mapping macros here.
        //    DO NOT EDIT what you see in these blocks of generated code !
    return 0;

The WM_SIZEPARENT message gets sent by the handler we'll be adding to CMainFrame for the WM_SIZE message. But first, a preliminary. Notice how I mentioned above that the centering of a given MDI child window can be thrown off if, say, the user hides or shows the toolbar(s) or status bar? Let's also account for this. First, an aside on the structure of the main window.

Window Handles and the MDIClient

Window handles exist to denote windows, and they are useful to pass to various Windows API functions when we want to do something to the corresponding window. It turns out that the client area of the main window of a typical MFC application is filled by a window called the MDIClient. It is actually the MDIClient which is the parent of all the MDI child windows currently open in the main window. The window handle of the MDIClient is stored in the CMDIFrameWnd::m_hWndMDIClient member variable.

In order to get the WM_SIZEPARENT message sent out to all the MDI child windows (since we never know a priori just which MDI child windows are open at any given time), we are going to ask the MDIClient to worry about delivering the said message to all its children. We employ CWnd::FromHandle, which is a static function, to get a CWnd pointer to the MDIClient, and then use CWnd::SendMessageToDescendants to send the WM_SIZEPARENT message to the MDI child windows. As may be guessed from its name, CWnd::SendMessageToDescendants simply sends the specified messages to the given CWnd's child windows, whichever windows those are.

Override CFrameWnd::RecalcLayout() to Send WM_SIZEPARENT

When the user hides or shows the toolbar(s) and the status bar, the framework calls CFrameWnd::RecalcLayout to handle the repositioning of child windows and other elements of the main window. RecalcLayout is a virtual function, which we may override. Since, resizing the main window also amounts to modifying its 'layout'. So let's make our override of RecalcLayout be in charge of sending the WM_SIZEPARENT messages to the MDI child windows currently in the main window.

Open up ClassWizard, and select the CMainFrame class, and override RecalcLayout. We are going to employ the approach mentioned above. Fill in the code shown below in bold:

Listing 5: Overriding CMDIFrameWnd::RecalcLayout

void CMainFrame::RecalcLayout(BOOL bNotify) 
    // Call base class first

    if (::IsWindow(m_hWndMDIClient)) {
        CWnd* pClientWnd = CWnd::FromHandle(m_hWndMDIClient);

        // Hopefully this should notify CMDIChildWnds that their
        // client area is changing size -- better re-center themselves!
            0, 0, FALSE, FALSE);

Note how we call IsWindow to check that the m_hWndMDIClient handle is valid, before proceeding. This is critical if your application automatically creates, e.g., a new document initially on startup. The first time RecalcLayout is called by the framework is before the MDIClient is created, so at this point, CWnd::FromHandle will cause an exception if you try to get a CWnd* pointer from the (now invalid) m_hWndMDIClient handle.

Handle the WM_SIZE Message in CMainFrame

OK, so now if the user hides or shows the toolbar(s) or status bar, we are covered. What about if they move, resize, minimize, maximize, or restore the main window? Odds are nothing will happen. To update the centering of the MDI child window(s) open in the main window, we need to handle the WM_SIZE message. In the message handler, we'll call our RecalcLayout override to do the dirty work. Here's the code (you add the code shown in bold after using ClassWizard to create the handler):

Listing 6: Handling WM_SIZE

void CMainFrame::OnSize(UINT nType, int cx, int cy) 
    CMDIFrameWnd::OnSize(nType, cx, cy);


That's it, we're done. The program should now center its MDI child window(s) upon creation. And resizing/moving etc. the window, or hiding or showing the toolbar(s) or status bar should leave the open MDI child window(s) unscathed.


This article originally appeared in Visual C++ Developer, a monthly magazine produced by Pinnacle Publishing, in October 1998. This article content is under copyright of the author and may not be reprinted without express written permission.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Brian C Hart
Software Developer (Senior) xyLOGIX, LLC
United States United States
From Fridley, Minnesota and I like computer programming! When I got started, I was working mostly with Windows GUI programming in C/C++. Then later on I worked with COM/DCOM for a school internship. I used COM/DCOM to write an ad hoc cluster server and job-running environment for a cluster of 24 Windows-based high-end visualization workstations. I moved on to C# and have been working in C# and Windows Forms ever since. I have yet to embrace Silverlight Smile | :)

You may also be interested in...

Comments and Discussions

Generalprinting from CScrollView Pin
vikas amin3-Oct-05 4:09
membervikas amin3-Oct-05 4:09 
Generalcom Pin
Santosh Kumar793-Oct-05 2:45
memberSantosh Kumar793-Oct-05 2:45 
GeneralRe: com Pin
Bankey Khandelwal10-Jan-06 20:38
memberBankey Khandelwal10-Jan-06 20:38 
Best book for Com at beginner level is "Inside COM"
QuestionHow about maximize?? Pin
Tcpip200525-Apr-05 1:30
memberTcpip200525-Apr-05 1:30 
AnswerRe: How about maximize?? Pin
mhorowit26-Sep-07 19:54
membermhorowit26-Sep-07 19:54 
Generalhelp.i can't open the zip file. Pin
alidiedie25-Feb-03 3:42
memberalidiedie25-Feb-03 3:42 
GeneralRe: help.i can't open the zip file. Pin
Brian Hart7-Apr-05 12:07
memberBrian Hart7-Apr-05 12:07 
GeneralWow!!! Pin
PJ Arends9-Apr-05 11:24
memberPJ Arends9-Apr-05 11:24 
Generalquestion, please help me out Pin
quin21-Dec-02 19:26
sussquin21-Dec-02 19:26 
GeneralRe: question, please help me out Pin
Brian Hart9-Apr-05 12:15
memberBrian Hart9-Apr-05 12:15 
GeneralAnother way... Pin
Ravi Bhavnani21-Oct-02 9:26
memberRavi Bhavnani21-Oct-02 9:26 
GeneralRe: Another way... Pin
FDogX31-Mar-04 21:43
memberFDogX31-Mar-04 21:43 
GeneralRe: Another way... Pin
Ravi Bhavnani1-Apr-04 2:34
memberRavi Bhavnani1-Apr-04 2:34 
GeneralRe: Another way... Pin
Brian Hart31-Mar-04 21:51
memberBrian Hart31-Mar-04 21:51 
GeneralRe: Another way... Pin
Ravi Bhavnani1-Apr-04 2:33
memberRavi Bhavnani1-Apr-04 2:33 
Generalgood, ravi, simple and works fine ! Pin
michael zhao2-Apr-05 17:04
membermichael zhao2-Apr-05 17:04 
GeneralRe: good, ravi, simple and works fine ! Pin
Brian Hart3-Apr-05 17:15
memberBrian Hart3-Apr-05 17:15 
Generalok Pin
Starodubtsev Sergey10-Feb-01 6:37
memberStarodubtsev Sergey10-Feb-01 6:37 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.180111.1 | Last Updated 7 Apr 2005
Article Copyright 2000 by Brian C Hart
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid