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.
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.

Figure 19: Creating and adding the CStudent class files.

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.

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.

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:
MSDN MFC 9.0 class library online documentation - latest version.
DCOM at MSDN.
COM+ at MSDN.
COM at MSDN.
Unicode and Multi-byte character set: Story and program examples.