1. The Goal of Preserving the Window Size and Position
When we work on windows-based applications, we look at a lot of windows elements like a menu, toolbar, and status bar. The position and arrangement of one or more toolbars depend on the size of the window. Furthermore, one can also arrange the toolbar vertical or horizontal.
Let us say we arranged 7 of the toolbars in two rows on top of the window and in addition one toolbar on the left side. When we close and return to the application, all the toolbar states are gone. To avoid this, we have to preserve the windows position and size along with toolbar state while closing the application.
In this example, we will preserve the window size and its position relative to the desktop window using the WINDOWPLACEMENT structure. We will also use the SaveBarState function of CFrameWnd class to save the toolbar state.
2. The Default Behavior of the Application
First, create an SDI MFC application by accepting all the defaults in wizard. Run it, and drag the toolbar so that it appears on the left of the window. Then, resize the window and leave it towards the bottom left corner of the desktop. The window now looks as shown below:
When we reopen the application, the toolbar stays below the menu horizontally, and the window does not stay near the start menu as shown above. Additionally, we will not see our resized window and by all means, the customization that we did is lost. This is the default behavior of the MFC SDI application. OK, let us start the code change. We are going the write WINDOWPLACEMENT structure in the registry while closing the application. And when we open it again we read the registry to remember our last customization.
Video 1: Default behaviour of SDI Application – Does not preserve window position
3. Saving SDI Window State
3.1 Set an Application Key in the Registry
We are using the SetRegistryKey function of the CWinApp to create a Key Root for our example. In our case, we are creating HubPages as the Key. Now, have a look at the below code which is written in the InitInstance of CWinApp:
We are passing the HubPages as a string to the function SetRegistryKey and this will create a Key for us in the windows registry. The path is: HKEY_CURRENT_USER\Software\HubPages.
3.2 Save Toolbar and Window Position
We have our Registry entry ready. Now, we will save the Toolbar and window position into the registry under the sub-keys of HubPages. The correct time to preserve the window state to a registry is application closure. Add a handler for WM_CLOSE Message in the CMainFrame and this is where we will write our code to save the window state. In the below, we show how to create OnClose Handler for the WM_CLOSE message.
Video 2: Adding WM_CLOSE Handler for CMainFrame
The empty handler added by the Visual Studio IDE is below:
3.2.1 Declaration Required for Registry Access
We need to declare some variables to access the registry. We declared Registry_Key as an HKEY, or in simple terms, a Registry Handle which tells key location in the registry to which we need access. The WINDOWPLACEMENT is C++ structure which we will write into the Registry. The code is below:
3.2.2 Save the Toolbar State
The function SaveBarState will create one or more sub-key under the "HubPages". In our example, we are creating "MainToolBar" as sub-key for storing the toolbar state. The code is below:
At this stage, closing the application will create registry entries for string the Toolbar states. The Registry entries are shown in the below picture.
Do not get confused about the "PreservedWindowsPos" key as we will write code for that soon. The screenshot is taken after that code is executed once.
3.2.3 Save Window Position
To save the window position, first, we need to create a registry key. From the previous section, we know that the Parent key in the Registry is HubPages. Now, we will create a sub-key called PreservedWindowPos and inside this key we will write our Window Position. The below code first checks the Registry entry and when it doesn’t find one, it will create a new Registry entry for Window Size and Window Position. Below is the code:
Once, we have a valid Registry Key; we capture the Windows Size and Position in a structure called WINDOWPLACEMENT. The GetWindowPlacement Function will retrieve this information and it takes the WINDOWPLACEMENT structure as a parameter. After the call, we take the WINDOWPLACEMENT structure and write that to the Registry. Below is the code:
Note that while we close the window, its size and position are preserved in the registry. In the coming section, we will read this registry entry, create the structure for window placement and restore the window exactly as it was.
4. Loading Window Position and Size
Now, we have our window position and size in the registry. In this section, we will load those registry values and position the window in the same location while it was closed along with the preserved size.
1) In the below code, we are first restoring the toolbar state. The LoadBarState will load the toolbar settings from the registry and arranges the toolbar in the mainframe window. We added this code to the OnCreate Handler of the WM_CREATE Message.
2) In the application’s InitInstance, we declare the variables required to read the registry and load the WINDOWPLACEMENT structure. Below is the code:
3) While closing the application, we stored the WINDOWPLACEMENT structure in the registry key called PreservedWindowPos and now we open that key by calling RegOpenKeyEx. The handle to this registry key is stored in HKEY variable RegistryKey. We use this handle to query the Window placement information written as a structure in binary format.
4) At this moment, we have the registry information read into the structure called "sWP" and we can use this to restore our window to the previous state. Note that when the registry read is a success, we call SetWindowPlacement by supplying the structure we read from the registry. Below is the code for it:
You can look at the video below which shows how Windows is restored to its previous state between application sessions.
Video 3: Testing the Window Placement From Registry
© 2018 sirama