Click here to Skip to main content
15,886,518 members
Articles / Desktop Programming / MFC

A drop in class for saving and restoring window position

Rate me:
Please Sign up or sign in to vote.
3.50/5 (6 votes)
12 Mar 20034 min read 60.2K   1K   33  
This article describes how to save and restore the size and position of your dialog-based application.
// 
// Copyright(C) 1999-2003 toShay Consulting
// All rights reserved.
// 
// toShay Consulting grants you ("Licensee") a non-exclusive, royalty free, 
// licence to use, modify and redistribute this software in source and binary 
// code form, provided that i) this copyright notice and licence appear on all 
// copies of the software; and ii) Licensee does not utilize the software in a 
// manner which is disparaging to toShay Consulting.
//
// This software is provided "as is" without a warranty of any kind. All 
// express or implied conditions, representations and warranties, including
// any implied warranty of merchantability, fitness for a particular purpose
// or non-infringement, are hereby excluded. toShay Consulting and its licensors 
// shall not be liable for any damages suffered by licensee as a result of 
// using, modifying or distributing the software or its derivatives. In no
// event will toShay Consulting be liable for any lost revenue, profit or data,
// or for direct, indirect, special, consequential, incidental or punitive
// damages, however caused and regardless of the theory of liability, arising 
// out of the use of or inability to use software, even if toShay Consulting 
// has been advised of the possibility of such damages.
//
// This software is not designed or intended for use in on-line control of 
// aircraft, air traffic, aircraft navigation or aircraft communications; or in 
// the design, construction, operation or maintenance of any nuclear 
// facility. Licensee represents and warrants that it will not use or 
// redistribute the Software for such purposes. 
//
///////////////////////////////////////////////////////////////////////////////

// Strings used in saving and restoring window position information
// in the Registry.
const CString cs_RegEntry = "Settings";
const CString cs_RegKey   = "WindowPlacement";
// const CString cs_RegFormat = "%ld,%ld,%ld,%d,%d,%d,%d,%d,%d,%d,%d";

/// <summary>
/// CWindowPosition is a Singleton class for saving and restoring the position of a
/// window to a well-known location in the system registry.  It can be used as a 
/// drop-in module and requires only a few calls in the correct location to be
/// effective.  Unfortunately it cannot be done with a single line in the source 
/// since this would require depending on destructors firing at the right time,
/// and for most applications, by the time the destructor is called for this class,
/// there is no window left to query for its position information.  So, to use
/// this class, instantiate it somewhere convenient while starting your application.
/// 
/// If you prefer to have a more human readable form of the window position in the 
/// registry, use the cs_RegFormat variable above and the WriteProfileString and 
/// GetProfileString code below.
/// 
/// Here are the steps necessary for a complete implementation in a dialog application.
/// First, make sure that you have set a registry key for your application.  This is
/// typically done in the InitInstance() method of the application.
/// 
/// BOOL CWindowPositionApp::InitInstance()
/// {
///     // Standard initialization
///     .
///     . Other initialization code here
///     .
///     // Start WindowPlacement code block
///     {
///         // Set the registry key.  Otherwise application settings will be placed
///         // in an INI file in the Windows folder.
///         SetRegistryKey("WindowPositionApp");
///     }
///     // End WindowPlacement code block
///     
///     // For a dialog application the creation of the dialog is here
///     CMyDialog dlg;
///     dlg.DoModal();
///     .
///     . Other code here
///     .
///     
///     // Since the dialog has been closed, return FALSE so that we exit the
///     //  application, rather than start the application's message pump.
///     return FALSE;
/// }
/// 
/// // Include the window position header file
/// #include "WindowPosition.h"
/// 
/// class CMyDialog : public CDialog
/// {
/// private:
///     // Create the window position object and make it private
///     CWindowPosition m_WindowPosition;
/// 
///     // Construction
/// public:
///     CMyDialog(CWnd* pParent = NULL);    // standard constructor
///     
///     .
///     . Other code here
///     .
/// };
/// 
/// // Constructor
/// CMyDialog::CMyDialog(CWnd* pParent /*=NULL*/)
///     : CDialog(CMyDialog::IDD, pParent),
///     m_WindowPosition(this)
/// {
///     .
///     . Other constructor code here
///     .
/// }
/// 
/// BOOL CMyDialog::OnInitDialog()
/// {
///     CDialog::OnInitDialog();
///     .
///     .
///     .
///     // Start WindowPlacement code block
///     {
///         // Be sure to set the registry key in the main application module.  
///         // Otherwise application settings will be placed in an INI file in the 
///         // Windows folder.
/// 
///         // Set the pointer to the window whose position is to be saved/restored.
///         // You can also initialize it in the constructor if you wish.  Microsoft
///         // issues a 'warning C4355: 'this' : used in base member initializer list'
///         // if you do so, but it works nontheless.  We'll set it explicitly here.
///         m_WindowPosition.SetPositionWnd(this);
///         // Restore the window position, if previously saved.
///         m_WindowPosition.SetWindowPlacement();
///     }
///     // End WindowPlacement code block
///     
///     // TODO: Add extra initialization here
/// 
///     return TRUE;  // return TRUE  unless you set the focus to a control
/// }
/// 
/// // Override DestroyWindow() for a dialog application.
/// BOOL CMyDialog::DestroyWindow() 
/// {
///     m_WindowPosition.SaveWindowPlacement();
///     return CDialog::DestroyWindow();
/// }
/// 
/// </summary>
class CWindowPosition
{
private:
    CWnd* m_pPositionWnd;

public:
    CWindowPosition(CWnd* pPositionWnd = NULL) :
        m_pPositionWnd(pPositionWnd)
    {
    };

    virtual ~CWindowPosition()
    {
    };

    // The singleton
    static CWindowPosition&  Instance()
    { 
        static CWindowPosition theOnlyWindowPosition;
        return theOnlyWindowPosition; 
    };

    void SetPositionWnd(CWnd* pPositionWnd)
    {
        Instance().m_pPositionWnd = pPositionWnd;
    };
    
    void SaveWindowPlacement()
    {
        // Save the last window size and position
        WINDOWPLACEMENT wndpl;
        if (Instance().m_pPositionWnd && Instance().m_pPositionWnd->GetWindowPlacement(&wndpl))
        {
            CWinApp* pApp = AfxGetApp();
            ASSERT(pApp);
            /*
            CString strWP;
            strWP.Format(cs_RegFormat, 
                wndpl.flags,
                wndpl.length,
                wndpl.showCmd,
                wndpl.ptMaxPosition.x,
                wndpl.ptMaxPosition.y,
                wndpl.ptMinPosition.x,
                wndpl.ptMinPosition.y,
                wndpl.rcNormalPosition.left, 
                wndpl.rcNormalPosition.top, 
                wndpl.rcNormalPosition.right,
                wndpl.rcNormalPosition.bottom);

            pApp->WriteProfileString(cs_RegEntry, cs_RegKey, strWP);
            */
            if (pApp)
            {
                pApp->WriteProfileBinary(cs_RegEntry, cs_RegKey, (BYTE*)&wndpl, sizeof(wndpl));
            }
        }
    };

    void SetWindowPlacement()
    {
        CWinApp* pApp = AfxGetApp();

        if (pApp)
        {
            /*
            WINDOWPLACEMENT wndpl;

            CString strWP;
            strWP = pApp->GetProfileString(cs_RegEntry, cs_RegKey, NULL);

            if (!strWP.IsEmpty())
            {
                sscanf(strWP, cs_RegFormat, 
                    &wndpl.flags,
                    &wndpl.length,
                    &wndpl.showCmd,
                    &wndpl.ptMaxPosition.x,
                    &wndpl.ptMaxPosition.y,
                    &wndpl.ptMinPosition.x,
                    &wndpl.ptMinPosition.y,
                    &wndpl.rcNormalPosition.left, 
                    &wndpl.rcNormalPosition.top, 
                    &wndpl.rcNormalPosition.right,
                    &wndpl.rcNormalPosition.bottom);

                Instance().m_pPositionWnd->SetWindowPlacement(&wndpl);
            }
            */
            WINDOWPLACEMENT* pwndpl;
            BYTE* pb = NULL;
            UINT nLen = 0;
            if (pApp && pApp->GetProfileBinary(cs_RegEntry, cs_RegKey, &pb, &nLen))
            {
                pwndpl = reinterpret_cast<WINDOWPLACEMENT*>(pb);
                Instance().m_pPositionWnd->SetWindowPlacement(pwndpl);
                free(pb);
            }

        }
    };
};

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

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


Written By
Tonga Tonga
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions