| Tenouk C & C++ | MFC Home | MDI Serialization 3 | Printing & Print Preview 1 | Download | Site Index |


 

 

 

 

 

 

Module 12c:

Serialization: Reading and Writing Documents—MDI Applications 4

 

 

 

 

 

 

 

This is a continuation from previous module... Program examples compiled using Visual C++ 6.0 (MFC 6.0) compiler on Windows XP Pro machine with Service Pack 2. Topics and sub topics for this Tutorial are listed below. You can compare the standard C file I/O, standard C++ file I/O and Win32 directory, file and access controls with the MFC serialization. So many things lor! Similar but not same. Those links also given at the end of this tutorial.

  1. CMymfc18View Class

  2. CStudent Class

  3. Testing the MYMFC18 Application

 

 

CMymfc18View Class

 

Listing 9 shows the code for the CMymfc18View class similar with the MYMFC17 and MYMFC16 program examples.

 

MYMFC18VIEW.H

// Mymfc18View.h : interface of the CMymfc18View class

//

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

 

#if !defined(AFX_MYMFC18VIEW_H__4D011049_7E1C_11D0_8FE0_00C04FC2A0C2__INCLUDED_)

#define AFX_MYMFC18VIEW_H__4D011049_7E1C_11D0_8FE0_00C04FC2A0C2__INCLUDED_

 

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

 

class CMymfc18View : public CFormView

{

protected:

    POSITION      m_position; // current position in document list

    CStudentList* m_pList;    // copied from document

 

protected: // create from serialization only

    CMymfc18View();

    DECLARE_DYNCREATE(CMymfc18View)

 

public:

    //{{AFX_DATA(CMymfc18View)

    enum { IDD = IDD_MYMFC18_FORM };

    int     m_nGrade;

    CString m_strName;

    //}}AFX_DATA

 

// Attributes

public:

    CMymfc18Doc* GetDocument();

 

// Operations

public:

 

// Overrides

    // ClassWizard generated virtual function overrides

    //{{AFX_VIRTUAL(CMymfc18View)

    public:

    virtual BOOL PreCreateWindow(CREATESTRUCT& cs);

    protected:

    virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support

    virtual void OnInitialUpdate(); // called first time after construct

    virtual void OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint);

    //}}AFX_VIRTUAL

 

// Implementation

public:

    virtual ~CMymfc18View();

#ifdef _DEBUG

    virtual void AssertValid() const;

    virtual void Dump(CDumpContext& dc) const;

#endif

 

protected:

    virtual void ClearEntry();

    virtual void InsertEntry(POSITION position);

    virtual void GetEntry(POSITION position);

 

// Generated message map functions

protected:

    //{{AFX_MSG(CMymfc18View)

    afx_msg void OnClear();

    afx_msg void OnStudentHome();

    afx_msg void OnStudentEnd();

    afx_msg void OnStudentPrev();

    afx_msg void OnStudentNext();

    afx_msg void OnStudentIns();

    afx_msg void OnStudentDel();

    afx_msg void OnUpdateStudentHome(CCmdUI* pCmdUI);

    afx_msg void OnUpdateStudentEnd(CCmdUI* pCmdUI);

    afx_msg void OnUpdateStudentDel(CCmdUI* pCmdUI);

    //}}AFX_MSG

    DECLARE_MESSAGE_MAP()

};

 

#ifndef _DEBUG  // debug version in Mymfc18View.cpp

inline CMymfc18Doc* CMymfc18View::GetDocument()

   { return (CMymfc18Doc*)m_pDocument; }

#endif

 

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

 

//{{AFX_INSERT_LOCATION}}

// Microsoft Visual C++ will insert additional declarations

// immediately before the previous line.

 

#endif // !defined(AFX_MYMFC18VIEW_H__4D011049_7E1C_11D0_8FE0_00C04FC2A0C2__INCLUDED_)

 

 

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

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

MYMFC18VIEW.CPP

// Mymfc18View.cpp : implementation of the CMymfc18View class

//

 

#include "stdafx.h"

#include "mymfc18.h"

 

#include "MYMFC18DOC.h"

#include "Mymfc18View.h"

 

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[ ] = __FILE__ ;

#endif

 

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

// CMymfc18View

 

IMPLEMENT_DYNCREATE(CMymfc18View, CFormView)

BEGIN_MESSAGE_MAP(CMymfc18View, CFormView)

    //{{AFX_MSG_MAP(CMymfc18View)

    ON_BN_CLICKED(IDC_CLEAR, OnClear)

    ON_COMMAND(ID_STUDENT_HOME, OnStudentHome)

    ON_COMMAND(ID_STUDENT_END, OnStudentEnd)

    ON_COMMAND(ID_STUDENT_PREV, OnStudentPrev)

    ON_COMMAND(ID_STUDENT_NEXT, OnStudentNext)

    ON_COMMAND(ID_STUDENT_INS, OnStudentIns)

    ON_COMMAND(ID_STUDENT_DEL, OnStudentDel)

    ON_UPDATE_COMMAND_UI(ID_STUDENT_HOME, OnUpdateStudentHome)

    ON_UPDATE_COMMAND_UI(ID_STUDENT_END, OnUpdateStudentEnd)

    ON_UPDATE_COMMAND_UI(ID_STUDENT_PREV, OnUpdateStudentHome)

    ON_UPDATE_COMMAND_UI(ID_STUDENT_NEXT, OnUpdateStudentEnd)

    ON_UPDATE_COMMAND_UI(ID_STUDENT_DEL, OnUpdateStudentDel)

    //}}AFX_MSG_MAP

END_MESSAGE_MAP()

 

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

// CMymfc18View construction/destruction

 

CMymfc18View::CMymfc18View() : CFormView(CMymfc18View::IDD)

{

    TRACE("Entering CMymfc18View constructor\n");

    //{{AFX_DATA_INIT(CMymfc18View)

    m_nGrade = 0;

    m_strName = _T("");

    //}}AFX_DATA_INIT

    m_position = NULL;

}

 

CMymfc18View::~CMymfc18View()

{

}

 

void CMymfc18View::DoDataExchange(CDataExchange* pDX)

{

    CFormView::DoDataExchange(pDX);

    //{{AFX_DATA_MAP(CMymfc18View)

    DDX_Text(pDX, IDC_GRADE, m_nGrade);

    DDV_MinMaxInt(pDX, m_nGrade, 0, 100);

    DDX_Text(pDX, IDC_NAME, m_strName);

    DDV_MaxChars(pDX, m_strName, 20);

    //}}AFX_DATA_MAP

}

BOOL CMymfc18View::PreCreateWindow(CREATESTRUCT& cs)

{

    // TODO: Modify the Window class or styles here by modifying

    //  the CREATESTRUCT cs

    return CFormView::PreCreateWindow(cs);

}

 

void CMymfc18View::OnInitialUpdate()

{

    TRACE("Entering CMymfc18View::OnInitialUpdate\n");

    m_pList = GetDocument()->GetList();

    CFormView::OnInitialUpdate();

}

 

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

// CMymfc18View diagnostics

 

#ifdef _DEBUG

void CMymfc18View::AssertValid() const

{

    CFormView::AssertValid();

}

 

void CMymfc18View::Dump(CDumpContext& dc) const

{

    CFormView::Dump(dc);

}

 

CMymfc18Doc* CMymfc18View::GetDocument() // non-debug version is inline

{

    ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMymfc18Doc)));

    return (CMymfc18Doc*)m_pDocument;

}

#endif //_DEBUG

 

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

// CMymfc18View message handlers

 

void CMymfc18View::OnClear()

{

    TRACE("Entering CMymfc18View::OnClear\n");

    ClearEntry();

}

 

void CMymfc18View::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)

{

    // called by OnInitialUpdate and by UpdateAllViews

    TRACE("Entering CMymfc18View::OnUpdate\n");

    m_position = m_pList->GetHeadPosition();

    GetEntry(m_position); // initial data for view

}

 

void CMymfc18View::OnStudentHome()

{

    TRACE("Entering CMymfc18View::OnStudentHome\n");

    // need to deal with list empty condition

    if (!m_pList->IsEmpty()) {

        m_position = m_pList->GetHeadPosition();

        GetEntry(m_position);

    }

}

 

void CMymfc18View::OnStudentEnd()

{

    TRACE("Entering CMymfc18View::OnStudentEnd\n");

    if (!m_pList->IsEmpty()) {

        m_position = m_pList->GetTailPosition();

        GetEntry(m_position);

    }

}

 

void CMymfc18View::OnStudentPrev()

{

    POSITION pos;

    TRACE("Entering CMymfc18View::OnStudentPrev\n");

    if ((pos = m_position) != NULL) {

        m_pList->GetPrev(pos);

        if (pos) {

            GetEntry(pos);

      m_position = pos;

        }

    }

}

 

void CMymfc18View::OnStudentNext()

{

    POSITION pos;

    TRACE("Entering CMymfc18View::OnStudentNext\n");

    if ((pos = m_position) != NULL) {

        m_pList->GetNext(pos);

        if (pos) {

            GetEntry(pos);

            m_position = pos;

        }

    }

}

void CMymfc18View::OnStudentIns()

{

    TRACE("Entering CMymfc18View::OnStudentIns\n");

    InsertEntry(m_position);

    GetDocument()->SetModifiedFlag();

    GetDocument()->UpdateAllViews(this);

}

 

void CMymfc18View::OnStudentDel()

{

    // deletes current entry and positions to next one or head

    POSITION pos;

    TRACE("Entering CMymfc18View::OnStudentDel\n");

    if ((pos = m_position) != NULL) {

        m_pList->GetNext(pos);

        if (pos == NULL) {

            pos = m_pList->GetHeadPosition();

            TRACE("GetHeadPos = %ld\n", pos);

            if (pos == m_position) {

                pos = NULL;

            }

        }

        GetEntry(pos);

        CStudent* ps = m_pList->GetAt(m_position);

        m_pList->RemoveAt(m_position);

        delete ps;

        m_position = pos;

        GetDocument()->SetModifiedFlag();

        GetDocument()->UpdateAllViews(this);

    }

}

 

void CMymfc18View::OnUpdateStudentHome(CCmdUI* pCmdUI)

{

    // called during idle processing and when Student menu drops down

    POSITION pos;

 

    // enables button if list not empty and not at home already

    pos = m_pList->GetHeadPosition();

    pCmdUI->Enable((m_position != NULL) && (pos != m_position));

}

 

void CMymfc18View::OnUpdateStudentEnd(CCmdUI* pCmdUI)

{

    // called during idle processing and when Student menu drops down

    POSITION pos;

 

    // enables button if list not empty and not at end already

    pos = m_pList->GetTailPosition();

    pCmdUI->Enable((m_position != NULL) && (pos != m_position));

}

 

void CMymfc18View::OnUpdateStudentDel(CCmdUI* pCmdUI)

{

    // called during idle processing and when Student menu drops down

    pCmdUI->Enable(m_position != NULL);

}

 

void CMymfc18View::GetEntry(POSITION position)

{

    if (position) {

        CStudent* pStudent = m_pList->GetAt(position);

        m_strName = pStudent->m_strName;

        m_nGrade = pStudent->m_nGrade;

    }

    else {

        ClearEntry();

    }

    UpdateData(FALSE);

}

 

void CMymfc18View::InsertEntry(POSITION position)

{

    if (UpdateData(TRUE)) {

        // UpdateData returns FALSE if it detects a user error

        CStudent* pStudent = new CStudent;

        pStudent->m_strName = m_strName;

        pStudent->m_nGrade = m_nGrade;

        m_position = m_pList->InsertAfter(m_position, pStudent);

    }

}

 

void CMymfc18View::ClearEntry()

{

    m_strName = "";

    m_nGrade = 0;

    UpdateData(FALSE);

    ((CDialog*) this)->GotoDlgCtrl(GetDlgItem(IDC_NAME));

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Listing 9: The CMymfc18View class listing.

 

 

CStudent Class

 

The following steps and code are for the CStudent class. It is similar to the project example of the previous module, add to the project new Student.h and Student.cpp files and paste the codes. Then do some code modification.

 

Creating and adding the CStudent class files.

 

Figure 19: Creating and adding the CStudent class files.

 

Entering the Student.cpp file name.

 

Figure 20: Entering the Student.cpp file name.

 

STUDENT.H

// student.h

 

#ifndef _INSIDE_VISUAL_CPP_STUDENT

#define _INSIDE_VISUAL_CPP_STUDENT

 

class CStudent : public CObject

{

    DECLARE_SERIAL(CStudent)

public:

    CString m_strName;

    int m_nGrade;

 

    CStudent()

    {

        m_nGrade = 0;

    }

 

    CStudent(const char* szName, int nGrade) : m_strName(szName)

    {

        m_nGrade = nGrade;

    }

 

    CStudent(const CStudent& s) : m_strName(s.m_strName)

    {

        // copy constructor

        m_nGrade = s.m_nGrade;

    }

 

    const CStudent& operator =(const CStudent& s)

    {

        m_strName = s.m_strName;

        m_nGrade = s.m_nGrade;

        return *this;

    }

 

    BOOL operator ==(const CStudent& s) const

    {

        if ((m_strName == s.m_strName) && (m_nGrade == s.m_nGrade))

              {

            return TRUE;

        }

        else

              {

            return FALSE;

        }

    }

 

    BOOL operator !=(const CStudent& s) const

    {

        // Let's make use of the operator we just defined!

        return !(*this == s);

    }

#ifdef _DEBUG

    void Dump(CDumpContext& dc) const;

#endif // _DEBUG

};

 

#endif // _INSIDE_VISUAL_CPP_STUDENT

 

typedef CTypedPtrList<CObList, CStudent*> CStudentList;

 

 

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

 

 

STUDENT.CPP

#include "stdafx.h"

#include "student.h"

 

IMPLEMENT_SERIAL(CStudent, CObject, 0)

 

#ifdef _DEBUG

void CStudent::Dump(CDumpContext& dc) const

{

    CObject::Dump(dc);

    dc << "m_strName = " << m_strName << "\nm_nGrade = " <<m_nGrade;

}

#endif // _DEBUG

 

 

Listing 10.

 

The use of the MFC template collection classes requires the following statement in StdAfx.h:

 

#include <afxtempl.h>

 

 

Listing 11.

 

The MYMFC18 Student.h file is almost the same as the file in the MYMFC16 project. The header contains the macro:

 

DECLARE_SERIAL(CStudent)

 

instead of:

 

DECLARE_DYNAMIC(CStudent)

 

 

Listing 12.

 

 

and the implementation file contains the macro:

 

IMPLEMENT_SERIAL(CStudent, CObject, 0)

 

instead of:

 

IMPLEMENT_DYNAMIC(CStudent, Cobject)

 

 

Listing 13.

 

The virtual Serialize function has also been added.

 

Testing the MYMFC18 Application

 

Do the build, run the program from Visual C++, and then make several documents.

 

MYMFC18’s MDI program output with serialization in action.

 

Figure 21: MYMFC18’s MDI program output with serialization in action.

 

Try saving the documents on disk, closing them, and reloading them. Also, choose New Window from the Window menu. Notice that you now have two views (and child frames) that attached to the same document.

 

Opening the saved MDI documents.

 

Figure 22: Opening the saved MDI documents.

 

Now exit the program and start Windows Explorer. The files you created should show up with document icons. Double-click on a document icon and see whether the MYMFC18 program starts up. Now, with both Windows Explorer and MYMFC18 on the desktop, drag a document from Windows Explorer to MYMFC18. Was the file opened?

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Further reading and digging:

  1. Standard C File Input/Output.

  2. Standard C++ File Input/Output.

  3. Win32 File Input/Output: Module C, Module D and Module E.

  4. MSDN MFC 7.0 class library online documentation.

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

  6. MSDN Library

  7. Windows data type.

  8. Win32 programming Tutorial.

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

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

 


 

| Tenouk C & C++ | MFC Home | MDI Serialization 3 | Printing & Print Preview 1 | Download | Site Index |