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

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • Live Event Date: October 29, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT It's well understood how critical version control is for code. However, its importance to DevOps isn't always recognized. The 2014 DevOps Survey of Practice shows that one of the key predictors of DevOps success is putting all production environment artifacts into version control. In this eSeminar, Gene Kim will discuss these survey findings and will share woeful tales of artifact management gone wrong! Gene will also share examples of how …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds