Click here to Skip to main content
Click here to Skip to main content

Automatic resizing of a FormView based application when the user toggles the control bars on or off.

, 26 Feb 2004
Rate this:
Please Sign up or sign in to vote.
Explains how to implement an application which automatically resizes itself when the user toggles the control bars on or off. This means that for an application using a CFormView derived view, the size of the view will be constant, the parent frame will be resized to fit control bars like status bar

Figure 1: The application window fits the whole client window exactly plus a statusbar and some toolbars.

Figure 2: One of the toolbars is docked to the side, one floating and the statusbar is removed. The application window is resized automatically to still just fit the client window.

Introduction

I created a SDI application where I put all the controls on the view, having it derived from CFormView. The application also had a couple of controlbars, like a statusbar and a few dockable toolbars. When the application started, I had the view and the parent frame resized to snugly fit my controls on it. However, when a user would toggle on or off my toolbars or the statusbar, the size of the frame window, it was either too big or too small to display the view. All my hard work with resizing the application is wasted. So I added some code, so my CMainFrame class could resize itself whenever the user toggled on or off the controlbars to fit the view. Not very complicated, but it took me some time to figure out how to do it most effectively.

Details

Below are the steps to create a CMainFrame class with automatic resizing. See also attached source code for a full demo application and more explanations.

  1. Create a Single Doc Application with a view derived from CFormView.
  2. Using Class Wizard, for MainFrame, add a message handler for the message called RecalcLayout.
  3. Add private int members called m_nControlBarsWidth and m_nControlBarsHeight in the CMainFrame class and initialize them to 0 in the constructor.
  4. Add a private bool member called m_bCtrlBarsChanged in the CMainFrame class and initialize it to false in the constructor.
  5. Change the implementation of CMainFrame::RecalcLayout to the following:
void CMainFrame::RecalcLayout(BOOL bNotify) 
{
    // RecalcLayout is called by MFC when the frame window is resized. 
    // In thisimplementation of RecalcLayout, the application  
    // call SetWindowPos, which will resize the frame window.
    // Therefore, if RecalcLayout is called because 
    // the application is resizing the frame we want to ignore that call.
    // We use m_bCtrlBarsChanged to keep track if the application are  
    // resizing the frame window because the user toggled the controlbars  
    // on or off or if the user is resizing the window.

    if (m_bCtrlBarsChanged)
    { 
        // Ignore call since it's triggered by our call to SetWindowPos. 
        // Otherwise we will end up looping.

        return;
    }

    if (!IsIconic() && !IsZoomed())
    {
        // Calculate size of controlbars (statusbar and toolbars).  
        // We should only do this when the window is not maximized 
        // or minimized. When maximized we should not change
        // the window's size, it should stay maximized. I don't think this 
        // function can be called when window is minimized,
        // but if so then window size
        // should not be changed either.

        int nControlBarsHeightCurrent = 0;
        int nControlBarsWidthCurrent = 0;


        // Calculate the current total height and width of our controlbars.
        // We only care of a controlbar's height or width
        // depending on how it is docked.

        // We will use CWnd::RepositionBars() with
        // the reposQuery parameter to get 
        // measurements of our controlbars. 

        // A statusbar is always docked to bottom so only
        // height of statusbar is interesting.

        CRect rectControlBar;

        RepositionBars(AFX_IDW_STATUS_BAR, AFX_IDW_STATUS_BAR, 
           AFX_IDW_PANE_FIRST, reposQuery, &rectControlBar, NULL, FALSE);
        nControlBarsHeightCurrent += rectControlBar.Height();

        // Toolbars can be docked to any side of the frame so
        // depending on if a toolbar is added to the top or bottom
        // or if docked to left or right side, we need to 
        // add check its height or width.

        RepositionBars(AFX_IDW_DOCKBAR_TOP, AFX_IDW_DOCKBAR_TOP, 
           AFX_IDW_PANE_FIRST, reposQuery, &rectControlBar, NULL, FALSE);
        nControlBarsHeightCurrent += rectControlBar.Height();

        RepositionBars(AFX_IDW_DOCKBAR_BOTTOM, AFX_IDW_DOCKBAR_BOTTOM, 
           AFX_IDW_PANE_FIRST, reposQuery, &rectControlBar, NULL, FALSE);
        nControlBarsHeightCurrent += rectControlBar.Height();

        RepositionBars(AFX_IDW_DOCKBAR_LEFT, AFX_IDW_DOCKBAR_LEFT, 
           AFX_IDW_PANE_FIRST, reposQuery, &rectControlBar, NULL, FALSE);
        nControlBarsWidthCurrent += rectControlBar.Width();

        RepositionBars(AFX_IDW_DOCKBAR_RIGHT, AFX_IDW_DOCKBAR_RIGHT, 
           AFX_IDW_PANE_FIRST, reposQuery, &rectControlBar, NULL, FALSE);
        nControlBarsWidthCurrent += rectControlBar.Width(); 

        if (nControlBarsHeightCurrent != m_nControlBarsHeight || 
            nControlBarsWidthCurrent != m_nControlBarsWidth)
        {
            // The size of the controlbars have changed.
            // Lets resize the frame window 
            // to accomodate this change. The goal is to keep
            // the client window unchanged
            // and resize the frame instead.

            // Set m_bCtrlBarsChanged to true so we know
            // the application is resizing the 
            // dialog, not the user.

            m_bCtrlBarsChanged = true;

            // nControlBarsWidthCurrent - m_nControlBarsWidth
            // is how much the bars have 
            // changed in width and that is how much
            // the frame's width should be adjusted.
            // The calculations for height is similar.

            // Get the current size of the frame window.

            CRect rectFrame;
            GetWindowRect(rectFrame);

            // Adjust the size of the frame window. 

            SetWindowPos(NULL, 0, 0, 
              rectFrame.Width() + 
              nControlBarsWidthCurrent - m_nControlBarsWidth, 
              rectFrame.Height() + 
              nControlBarsHeightCurrent - m_nControlBarsHeight,
              SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);

            // Save the size of the controlbars for next time
            // the user toggles the controlbars 
            // on or off so we know how much we should
            // adjust the size of the frame.

            m_nControlBarsWidth = nControlBarsWidthCurrent;
            m_nControlBarsHeight = nControlBarsHeightCurrent;

            // The application is finished resizing the dialog.

            m_bCtrlBarsChanged = false;
        }
    }

    CFrameWnd::RecalcLayout(bNotify);
}

Comments

CWnd::RepositionBars() is used to calculate the width and height of the different bars. It needs to be called differently depending on how our controlbars are docked.

If you want to add support for CMainFrame::OnGetMinMaxInfo (message handler for WM_GETMINMAXINFO), you need to do some extra coding, since the min size must also be updated when the user toggles control bars on or off. See the source code for how this is implemented.

Article History

The original article was posted on 28 Jan 2002. This update is done to fix a bug when the window was maximized and to handle several toolbars. Also side docking was not handled before. I added another picture to better show the code in action.

License

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

Share

About the Author

Patric_J
Web Developer
United States United States
I'm a software developer from Sweden who got tired of snow and cold weather and moved to USA. I choose New York City, so I wouldn't totally miss out on snow and cold weather. I work on Wall Street with financial systems (not much else to do in this neighborhood). I primarily use Visual C++/MFC or C#/.NET as development tool.
 
The picture is of my wife and me in Cannes, France, drinking the most expensive Coke we ever had.

Comments and Discussions

 
QuestionHow to disable frame resize Pinmemberazi_games23-Apr-03 10:06 
AnswerRe: How to disable frame resize Pinmemberdanglover23-May-03 1:07 
Add in Mainframe::PreCreateWindow...
the Line
cs.style &= ~(WS_MAXIMIZEBOX|WS_THICKFRAME);

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

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

| Advertise | Privacy | Mobile
Web02 | 2.8.141022.2 | Last Updated 27 Feb 2004
Article Copyright 2002 by Patric_J
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid