Restoring Window Position

Many applications need to "remember" the last window position and status (minimized/maximized/normal). This seemingly trivial task holds a few little-known subtleties, so I thought it might be helpful to show code that handles these things correctly.

Saving the window's position is straight forward:

void CMainFrame::OnClose() // message handler for WM_CLOSE
{
    // Save main window position
    CWinApp* app = AfxGetApp();
    WINDOWPLACEMENT wp;
    GetWindowPlacement(&wp);
    app->WriteProfileInt("Frame", "Status", wp.showCmd);
    app->WriteProfileInt("Frame", "Top",    wp.rcNormalPosition.top);
    app->WriteProfileInt("Frame", "Left",   wp.rcNormalPosition.left);
    app->WriteProfileInt("Frame", "Bottom", wp.rcNormalPosition.bottom);
    app->WriteProfileInt("Frame", "Right",  wp.rcNormalPosition.right);
	
    CFrameWnd::OnClose();
}

However, restoring it is a little more tricky:
BOOL CMainFrame::PreCreateWindow(CREATESTRUCT& cs)
{
    //
    // Restore main window position
    //

    CWinApp* app = AfxGetApp();
    int s, t, b, r, l;

    // only restore if there is a previously saved position
    if ( -1 != (s = app->GetProfileInt("Frame", "Status",   -1)) &&
         -1 != (t = app->GetProfileInt("Frame", "Top",      -1)) &&
         -1 != (l = app->GetProfileInt("Frame", "Left",     -1)) &&
         -1 != (b = app->GetProfileInt("Frame", "Bottom",   -1)) &&
         -1 != (r = app->GetProfileInt("Frame", "Right",    -1))
       ) {

        // restore the window's status
        app->m_nCmdShow = s;

        // restore the window's width and height
        cs.cx = r - l;
        cs.cy = b - t;

        // the following correction is needed when the taskbar is
        // at the left or top and it is not "auto-hidden"
        RECT workArea;
        SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0);
        l += workArea.left;
        t += workArea.top;

        // make sure the window is not completely out of sight
        int max_x = GetSystemMetrics(SM_CXSCREEN) -
                        GetSystemMetrics(SM_CXICON);
        int max_y = GetSystemMetrics(SM_CYSCREEN) -
                        GetSystemMetrics(SM_CYICON);
        cs.x = min(l, max_x);
        cs.y = min(t, max_y);
    }

    return CFrameWnd::PreCreateWindow(cs);
}

Date Posted: 6/24/98
Posted by: Pat Laplante.



Comments

  • MDI Child sized outside main frame

    Posted by Legacy on 10/23/2003 12:00am

    Originally posted by: m hayes

    I was using this technique to also remember MDI Child
    
    window positions.

    I had a problem when the main frame was resized smaller,
    and the user opened a MDI windows that were previously sized
    outside the current (smaller) main frame.

    You can check for this condition by adding this code
    immediately after loading the size from the registry:

    //Make sure that this size will be inside the main frame.
    CWnd *pTopFrame;
    CRect topFrameSize;
    if (pTopFrame = AfxGetMainWnd()->GetTopLevelFrame())
    {
    pTopFrame->GetClientRect(topFrameSize);

    //If the top of the child is below the main frame,
    //then move the child all the way to the top.
    if (rectSize.top > topFrameSize.bottom)
    rectSize.OffsetRect(0, rectSize.top * -1);

    //If the top of the child is to the right the main frame,
    //then move the child all the way to the left.
    if (rectSize.left > topFrameSize.right)
    rectSize.OffsetRect(rectSize.left * -1, 0);
    }

    Reply
  • Removing flicker when changing window size/position on creation

    Posted by Legacy on 11/07/2002 12:00am

    Originally posted by: Peter Robertson

    I am creating a window as follows:
    
    

    pDocTemplate = new CSingleDocTemplate(
    IDR_MAINFRAME,
    RUNTIME_CLASS(CmyDoc),
    RUNTIME_CLASS(CmyMainFrame),
    RUNTIME_CLASS(CmyView)
    );
    AddDocTemplate(pDocTemplate);
    if (!ProcessShellCommand(cmdInfo)) return FALSE;

    // Resize and Reposition...

    The ProcessShellCommand call displays the window with default size & position before I get a chance to set
    the values I want. The result is that I get a flicker
    with the default settings before the wanted ones appear.

    I have tried clearing WS_VISIBLE in all the places I
    can find, but the behaviour is always the same.

    Where __EXACTLY__ do you clear WS_VISIBLE to solve
    this problem, or should something else be done?

    Reply
  • A link to Jeff Prosise's article "Building Sticky Windows"

    Posted by Legacy on 11/20/1999 12:00am

    Originally posted by: Yuri Osipov

    Here is a link to profound article by Jeff Prosise
    "Building Sticky Windows" on the topic.
    Besides of the comments on the source very much alike to
    Sharon's one there are comments on the role of the
    'flags' member of WINDOWPLACEMENT structure and reaction
    on WM_ENDSESSION message.

    http://search.zdnet.com/pcmag/pctech/content/14.19/pp1419.001.html

    Reply
  • Restoring Window Position

    Posted by Legacy on 04/15/1999 12:00am

    Originally posted by: Pierre Morency

    Very nice piece of code.
    Trapping a "PreCreateWindow" call and going through a CREATESTRUCT to set the main window position, size and state was not obvious at all.
    Thanks again.

    Reply
  • problem in restoring the window size.

    Posted by Legacy on 04/09/1999 12:00am

    Originally posted by: madan

    i had tried with the code,i pop up the dialog box first,
    & then SDI,it is working with the dialog box,but with that
    i also want to restore the size of SDI mainframe ,
    though ,i am a new programmer in VC++,i need ur help,
    please ,solve my problem,
    help!!!!!!!
    madan.

    Reply
  • Nice piece of code.

    Posted by Legacy on 03/26/1999 12:00am

    Originally posted by: Kurt P. Gulden

    Just wanted to let you know that this is a nice piece of work. It droppped-right in to my MDI application. Cool!

    Reply
  • How to restore the CMDIChildWnd?

    Posted by Legacy on 03/11/1999 12:00am

    Originally posted by: nadir

    Hi,
    In my program, I have tried your code, it is fine to the main frame.
    While to the child frame, I could not find a proper place to deal with that
    // restore the window's status
    app->m_nCmdShow = s;
    How can I?
    Yours.

    Reply
  • creeps with CDialog

    Posted by Legacy on 01/09/1999 12:00am

    Originally posted by: ljp

    I plugged in the x and y to SetWindowPos on a CDialog App, and it creeps upward. Works great with Window App.

    Reply
  • How to over come the Flicker effects of the window creation ?

    Posted by Legacy on 11/11/1998 12:00am

    Originally posted by: Senthil

    Hai !
    
    how to avoid the display of window ( mainframe ) before it is restore

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • IBM Worklight is a mobile application development platform that lets you extend your business to mobile devices. It is designed to provide an open, comprehensive platform to build, run and manage HTML5, hybrid and native mobile apps.

  • Recently, Forrester Consulting conducted a Total Economic Impact™ (TEI) study to better understand the impact of incorporating Polycom voice solutions with Microsoft Lync. Forrester interviewed a company that had already deployed the Lync/Polycom combination to determine its potential return on investment (ROI). Microsoft Lync provides presence information and promotes voice and video collaboration. Polycom extends the benefits of Lync with voice endpoints and further enables collaboration in multiple …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds