65.9K
CodeProject is changing. Read more.
Home

A Better CenterWindow() Function

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.57/5 (4 votes)

Aug 8, 2000

viewsIcon

109477

downloadIcon

778

This is a good replacement for CWnd::CenterWindow() that works.

  • Download demo project - 42.2 Kb
  • Sample Image - CenterAnywhere1.gif
    Figure 1. The main CenterSample sample program screen.

    Introduction

    Centering windows on the screen is something which you can normally do with the CWnd::CenterWindow() function in MFC. CenterWindow() takes a pointer to a CWnd as its argument, and supposedly the function will center the window on which it's called against the window to which you pass it a pointer:

    pDlg->CenterWindow(AfxGetMainWnd()); // Centers pDlg against the main window?
    Listing 1. Demonstrating a use of CWnd::CenterWindow() to center a dialog.

    However, a question posed to the MFC Mailing List recently asked, "I have a dialog-based program, where the user can click a button and have a sub-dialog pop up. If I call CWnd::CenterWindow() in the sub-dialog's OnInitDialog() handler, the dialog will always be centered in the center of the screen, not centered with respect to the main dialog. How do I do this?"

    So I came up with a "Brute Force" centering function which actually works better than CWnd::CenterWindow(). It's called CSubDialog::CenterWindowOnOwner(), and I added to my sample program's sub-dialog's class, CSubDialog:

    void CSubDialog::CenterWindowOnOwner(CWnd* pWndToCenterOn)
    {
        // Get the client rectangle of the window on which we want to center
        // Make sure the pointer is not NULL first
    
        if (pWndToCenterOn == NULL)
            return;
     
        CRect rectToCenterOn;
        pWndToCenterOn->GetWindowRect(&rectToCenterOn);
    
        // Get this window's area
        CRect rectSubDialog;
        GetWindowRect(&rectSubDialog);
    
        // Now rectWndToCenterOn contains the screen rectangle of the window 
        // pointed to by pWndToCenterOn.  Next, we apply the same centering 
        // algorithm as does CenterWindow()
    
        // find the upper left of where we should center to
    
        int xLeft = (rectToCenterOn.left + rectToCenterOn.right) / 2 - 
            rectSubDialog.Width() / 2;
        int yTop = (rectToCenterOn.top + rectToCenterOn.bottom) / 2 - 
            rectSubDialog.Height() / 2;
    
        // Move the window to the correct coordinates with SetWindowPos()
        SetWindowPos(NULL, xLeft, yTop, -1, -1,
            SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
    }
    Listing 2. Our brute-force CenterWindowOnOwner() function.

    Then I added code to CSubDialog::OnInitDialog() to center it with respect to the main dialog, which is the main window of the application:

    BOOL CSubDialog::OnInitDialog()
    {
        CDialog::OnInitDialog();
    
        ...
    
        CWnd* pMainWnd = AfxGetMainWnd();
        CenterWindowOnOwner(pMainWnd);
    
        return TRUE;
    }
    Listing 3.How to call CenterWindowOnOwner().

    And voila! The sub-dialog will always center itself on the main dialog (or main application window), no matter where on the screen that window is placed.