visual-c++layoutmfcsdi

MFC, SDI app, Why the layout of views cannot be changed via code?


I'm new to MFC. I have just created an SDI application with the wizard, then tried to modify the generated code to control the layout of each view, toolbar, or menu:

...
m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC)
...
DockPane(&m_wndToolBar); // m_wndToolBar is a tool bar
...
DockPane(&m_wndFileView);
m_wndClassView.AttachToTabWnd(&m_wndFileView, DM_SHOW, TRUE, &pTabbedBar);
DockPane(&m_wndOutput);
// w_wndFileView, m_wndClassView, m_wndOutput are some views.
...

But it seems that it doesn't work: the windows always behave like they remember what the user operated at last time. For example, the last 3 lines of codes creates 3 views like this:

enter image description here

I run the code and closed, then modified them to:

DockPane(&m_wndFileView);
DockPane(&m_wndOutput);
m_wndClassView.AttachToTabWnd(&m_wndOutput, DM_SHOW, TRUE, &pTabbedBar);

I suppose it should appear like this but failed (This screenshot is not the run result, I changed the layout manually):

enter image description here

It keeps the layout as last time when closed (as picture 1). Additionally, any user's manual change of layout can remembered. So, why? Who said to do so?


Solution

  • By default, MFC SDI (and MDI) applications 'remember' the frame, menu and side-pane configurations between runs of the same application, which is achieved by writing/reading entries to/from the Windows Registry. Typically, for an application generated by the Visual Studio wizard, called "MySDIApp", this information will be located in a registry key named something like1:

    HKEY_CURRENT_USER\SOFTWARE\Local AppWizard-Generated Applications\MySDIApp
    

    In this, there will be a sub-key called "Workspace" and that will have numerous sub-entries, with names of the form "Pane-0123", "MFCToolBar-456", and so forth. To 'clear' all these remembered settings, you can simply delete that "Workspace" key using the registry editor.

    Alternatively, you can delete that key programmatically, by adding code like the following in your application class override of the OnInitInstance member (the code should be inserted between the wizard-generated lines indicated):

    BOOL CMySDIApp::InitInstance()
    {
        // Other wizard-generated and user code ...
    
        SetRegistryKey(_T("Local AppWizard-Generated Applications")); // Wizard-generated
        // Delete the remembered Workspace settings ...
        HKEY sk;
        CString kn;
        kn.Format(L"SOFTWARE\\%s\\%s", m_pszRegistryKey, m_pszAppName);
        if (RegOpenKeyEx(HKEY_CURRENT_USER, kn, 0, KEY_ALL_ACCESS, &sk) == ERROR_SUCCESS) {
            SHDeleteKey(sk, L"WorkSpace");
            RegCloseKey(sk);
        }
        LoadStdProfileSettings(4);  // Wizard-generated
    
        // More wizard-generated and user code ...
        return TRUE;
    }
    

    1 You can find the actual registry key by using the registry editor and searching for an entry named "BasePane--1"; this appears to be the first sub-key of the "Workspace" entry for wizard-generated (and other) MFC applications.