| Tenouk C & C++ | MFC Home | Reusable Frame Window Base Class 1 | Separating the Document from Its View 1 | Download | Site Index |


 

 

 

 

 

Module 9a:

A Reusable Frame Window Base Class 2

 

 

 

 

 

This is a continuation from the previous module... Program examples compiled using Visual C++ 6.0 (MFC 6.0) compiler on Windows XP Pro machine with Service Pack 2. Topic and sub topic if any for this Tutorial is listed below:

 

The MYMFC14 Example

 

The MYMFC14 program illustrates the use of a persistent frame window class, CPersistentFrame. Listing 1 shows the contents of the files Persist.h and Persist.cpp. In this example, you'll insert the new frame class into an AppWizard-generated SDI application. MYMFC14 is a "do-nothing" application, but you can insert the persistent frame class into any of your own SDI "do-something" applications.

 

PERSIST.H

// Persist.h

 

#ifndef _INSIDE_VISUAL_CPP_PERSISTENT_FRAME

#define _INSIDE_VISUAL_CPP_PERSISTENT_FRAME

 

class CPersistentFrame : public CFrameWnd

{ // remembers where it was on the desktop

    DECLARE_DYNAMIC(CPersistentFrame)

private:

    static const CRect s_rectDefault;

    static const char s_profileHeading[ ];

    static const char s_profileRect[ ];

    static const char s_profileIcon[ ];

    static const char s_profileMax[ ];

    static const char s_profileTool[ ];

    static const char s_profileStatus[ ];

    BOOL m_bFirstTime;

protected: // Create from serialization only

    CPersistentFrame();

    ~CPersistentFrame();

//{{AFX_VIRTUAL(CPersistentFrame)

    public:

    virtual void ActivateFrame(int nCmdShow = -1);

    protected:

    //}}AFX_VIRTUAL

 

    //{{AFX_MSG(CPersistentFrame)

    afx_msg void OnDestroy();

    //}}AFX_MSG

 

    DECLARE_MESSAGE_MAP()

};

 

#endif // _INSIDE_VISUAL_CPP_PERSISTENT_FRAME

 

 

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

PERSIST.CPP

// Persist.cpp Persistent frame class for SDI apps

 

#include "stdafx.h"

#include "persist.h"

 

#ifdef _DEBUG

#undef THIS_FILE

static char BASED_CODE THIS_FILE[ ] = __FILE__;

#endif

///////////////////////////////////////////////////////////////

// CPersistentFrame

 

const CRect CPersistentFrame::s_rectDefault(10,  10, 500, 400);  // static

const char CPersistentFrame::s_profileHeading[ ] = "Window size";

const char CPersistentFrame::s_profileRect[ ] = "Rect";

const char CPersistentFrame::s_profileIcon[ ] = "icon";

const char CPersistentFrame::s_profileMax[ ] = "max";

const char CPersistentFrame::s_profileTool[ ] = "tool";

const char CPersistentFrame::s_profileStatus[ ] = "status";

IMPLEMENT_DYNAMIC(CPersistentFrame, CFrameWnd)

 

BEGIN_MESSAGE_MAP(CPersistentFrame, CFrameWnd)

    //{{AFX_MSG_MAP(CPersistentFrame)

    ON_WM_DESTROY()

    //}}AFX_MSG_MAP

END_MESSAGE_MAP()

 

///////////////////////////////////////////////////////////////

CPersistentFrame::CPersistentFrame(){

    m_bFirstTime = TRUE;

}

 

///////////////////////////////////////////////////////////////

CPersistentFrame::~CPersistentFrame()

{    }

 

///////////////////////////////////////////////////////////////

void CPersistentFrame::OnDestroy()

{

    CString strText;

    BOOL bIconic, bMaximized;

    WINDOWPLACEMENT wndpl;

    wndpl.length = sizeof(WINDOWPLACEMENT);

    // gets current window position and

    //  iconized/maximized status

    BOOL bRet = GetWindowPlacement(&wndpl);

    if (wndpl.showCmd == SW_SHOWNORMAL) {

        bIconic = FALSE;

        bMaximized = FALSE;

    }

    else if (wndpl.showCmd == SW_SHOWMAXIMIZED) {

        bIconic = FALSE;

        bMaximized = TRUE;

    }

    else if (wndpl.showCmd == SW_SHOWMINIMIZED) {

        bIconic = TRUE;

        if (wndpl.flags) {

            bMaximized = TRUE;

        }

        else {

            bMaximized = FALSE;

        }

    }

    strText.Format("%04d %04d %04d %04d",

                   wndpl.rcNormalPosition.left,

                   wndpl.rcNormalPosition.top,

                   wndpl.rcNormalPosition.right,

                   wndpl.rcNormalPosition.bottom);

    AfxGetApp()->WriteProfileString(s_profileHeading, s_profileRect, strText);

    AfxGetApp()->WriteProfileInt(s_profileHeading, s_profileIcon, bIconic);

    AfxGetApp()->WriteProfileInt(s_profileHeading, s_profileMax, bMaximized);

    SaveBarState(AfxGetApp()->m_pszProfileName);

    CFrameWnd::OnDestroy();

}

 

///////////////////////////////////////////////////////////////

void CPersistentFrame::ActivateFrame(int nCmdShow)

{

    CString strText;

    BOOL bIconic, bMaximized;

    UINT flags;

    WINDOWPLACEMENT wndpl;

    CRect rect;

 

    if (m_bFirstTime) {

        m_bFirstTime = FALSE;

        strText = AfxGetApp()->GetProfileString(s_profileHeading, s_profileRect);

        if (!strText.IsEmpty()) {

            rect.left = atoi((const char*) strText);

            rect.top = atoi((const char*) strText + 5);

            rect.right = atoi((const char*) strText + 10);

            rect.bottom = atoi((const char*) strText + 15);

        }

        else {

            rect = s_rectDefault;

        }

       bIconic = AfxGetApp()->GetProfileInt(s_profileHeading, s_profileIcon, 0);

        bMaximized = AfxGetApp()->GetProfileInt(s_profileHeading, s_profileMax, 0);

        if (bIconic) {

            nCmdShow = SW_SHOWMINNOACTIVE;

            if (bMaximized) {

                flags = WPF_RESTORETOMAXIMIZED;

            }

            else {

                flags = WPF_SETMINPOSITION;

            }

        }

        else {

            if (bMaximized) {

                nCmdShow = SW_SHOWMAXIMIZED;

                flags = WPF_RESTORETOMAXIMIZED;

            }

            else {

                nCmdShow = SW_NORMAL;

                flags = WPF_SETMINPOSITION;

            }

        }

        wndpl.length = sizeof(WINDOWPLACEMENT);

        wndpl.showCmd = nCmdShow;

        wndpl.flags = flags;

        wndpl.ptMinPosition = CPoint(0, 0);

        wndpl.ptMaxPosition = CPoint(-::GetSystemMetrics(SM_CXBORDER), -::GetSystemMetrics(SM_CYBORDER));

        wndpl.rcNormalPosition = rect;

        LoadBarState(AfxGetApp()->m_pszProfileName);

        // sets window's position and minimized/maximized status

        BOOL bRet = SetWindowPlacement(&wndpl);

    }

    CFrameWnd::ActivateFrame(nCmdShow);

}

 

Listing 1: The CPersistentView class listing.

 

Here are the steps for building the MYMFC14 example program.

 

Run AppWizard to generate mfcproject\mymfc14 (or any other directory that you have designated your Visual C++ project for). Accept all default settings but two: select Single Document and deselect Printing and Print Preview and ActiveX Controls. The options and the default class names are shown in the following illustration.

 

MYMFC14 project summary.

 

Figure 1: MYMFC14 project summary.

 

Modify MainFrm.h. You must change the base class of CMainFrame. To do this, simply change the line:

 

class CMainFrame : public CFrameWnd

 

To:

 

class CMainFrame : public CPersistentFrame

 

 

Listing 1.

 

Also, add the line:

 

#include "persist.h"

 

 

Listing 2.

 

Modify MainFrm.cpp. Globally replace all occurrences of CFrameWnd with CPersistentFrame. Use the find and replace menu.

 

Visual C++ find and replace menu.

 

Figure 2: Visual C++ find and replace menu.

 

Replacing all occurrences of CFrameWnd with CPersistentFrame.

 

Figure 3: Replacing all occurrences of CFrameWnd with CPersistentFrame.

 

Modify mymfc14.cpp. Replace the line:

 

SetRegistryKey(_T("Local AppWizard-Generated Applications"));

 

With the line:

 

SetRegistryKey("Programming using Visual C++ and MFC");

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

------------------------------------------------------------------------------------

 

Listing 3.

 

Add the Persist.h and Persist.cpp file to the project. You can create the Persist.h and Persist.cpp files and add to the mymfc14 project as shown below and don’t forget to copy the source code for the Persist.h and Persist.cpp as shown in the previous listing into the files respectively then save those files. Don’t forget to make sure the Add to project check box is ticked.

 

Adding new files to the project.

 

Figure 4: Adding new files to the project.

 

Entering the new file name to be added to the project.

 

Figure 5: Entering the new file name to be added to the project.

 

Rebuild the ClassWizard file to include the new CPersistentFrame class.

 

Rebuilding the project to include new CPersistentFrame class.

 

Figure 6: Rebuilding the project to include new CPersistentFrame class.

 

Use Windows Explorer to delete the ClassWizard file mymfc14.clw.

 

Manually deleting the ClassWizard file mymfc14.clw file

 

Figure 7: Manually deleting the ClassWizard file mymfc14.clw file.

 

 

Back in Visual C++, choose ClassWizard from the View menu. Follow Visual C++'s instructions if it asks you to close any files. Click Yes when asked if you would like to rebuild the CLW file.

 

Rebuilding the CLW file dialog prompt.

 

Figure 8: Rebuilding the CLW file dialog prompt.

 

The Select Source Files dialog box will appear. Make sure all of the header and source files are listed in the Files In Project box, as shown in the following illustration.

 

Rebuilding the CLW file to integrate newly created class.

 

Figure 9: Rebuilding the CLW file to integrate newly created class.

 

Then click OK to regenerate the CLW file. Notice that CPersistentFrame is now integrated into ClassWizard. You'll now be able to map messages and override virtual functions in the CPersistentFrame class.

 

The CPersistentFrame is now integrated into ClassWizard after the CLW rebuilding.

 

Figure 10: The CPersistentFrame is now integrated into ClassWizard after the CLW rebuilding.

 

Build and test the MYMFC14 application. Resize and move the application's frame window, and then close the application.

 

MYMFC14 program output with persistent property.

 

Figure 11: MYMFC14 program output with persistent property.

 

When you restart the application, does its window open at the same location at which it was closed? Experiment with maximizing and minimizing, and then change the status and position of the control bars. Does the persistent frame remember its settings?

 

Save the CPersistentFrame class as a Gallery component for future use. In the ClassView window, right-click on CPersistentFrame and select Add To Gallery.

 

Saving our new created CPersistentFrame class for future use, class reusability.

 

Figure 12: Saving our new created CPersistentFrame class for future use, class reusability.

 

Bring up the Components And Controls Gallery by choosing Add To Project from the Project menu and then choosing Components And Controls.

 

Component and Controls menu used to save newly created class.

 

Figure 13: Component and Controls menu used to save newly created class.

 

Notice that Visual C++ created the file Persistent Frame.ogx in a folder named \mymfc14.

 

Persistent Frame.ogx file, the newly created class library.

 

Figure 14: Persistent Frame.ogx file, the newly created class library.

 

Change this folder's name to Persistent Frame. Now you can add the CPersistentFrame class to any project by simply adding Persistent Frame.ogx. We will add CPersistentFrame to mymfc22A project later.

 

Persistent frame directory that contain .ogx file, our newly created class.

 

Figure 15: Persistent frame directory that contain .ogx file, our newly created class.

 

Examine the Windows Registry. Run the Windows regedit.exe (or regedt32) program. Navigate to the HKEY_CURRENT_USER\Software\Programming Visual C++ and MFC\mymfc14 key.

 

Launching the registry editor at command line.

 

Figure 16: Launching the registry editor at command line.

 

You should see data values similar to those shown in the following illustration.

 

MYMFC14 project information in Registry.

 

Figure 17: MYMFC14 project information in Registry.

 

Notice the relationship between the Registry key and the SetRegistryKey() function parameter, "Programming using Visual C++ and MFC". If you supply an empty string as the SetRegistryKey() parameter, the program name (mymfc14, in this case) is positioned directly below the Software key.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Further reading and digging:

  1. MSDN MFC 7.0 class library online documentation.

  2. MSDN MFC 9.0 class library online documentation - latest version.

  3. Porting & Migrating your older programs.

  4. MSDN Library

  5. DCOM at MSDN.

  6. COM+ at MSDN.

  7. COM at MSDN.

  8. Windows data type.

  9. Win32 programming Tutorial.

  10. The best of C/C++, MFC, Windows and other related books.

  11. Unicode and Multibyte character set: Story and program examples.

 

 


 

| Tenouk C & C++ | MFC Home | Reusable Frame Window Base Class 1 | Separating the Document from Its View 1 | Download | Site Index |