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. Topics and sub topics for this Tutorial are listed below:
|
Data Members
The m_position data member is a kind of cursor for the document's collection. It contains the position of the CStudent object that is currently displayed. The m_pList variable provides a quick way to get at the student list in the document.
Listing 19.
OnInitialUpdate()
The virtual OnInitialUpdate() function is called when you start the application. It sets the view's m_pList data member for subsequent access to the document's list object.
Listing 20. |
OnUpdate()
The virtual OnUpdate() function is called both by the OnInitialUpdate() function and by the CDocument::UpdateAllViews function. It resets the list position to the head of the list, and it displays the head entry. In this example, the UpdateAllViews() function is called only in response to the Edit Clear All command. In a multiview application, you might need a different strategy for setting the CMymfc16View m_position variable in response to document updates from another view.
Listing 21.
Protected Virtual Functions
The following three functions are protected virtual functions that deal specifically with CStudent objects:
GetEntry().
InsertEntry().
ClearEntry().
Figure 32: Adding a protected virtual function using ClassView.
Listing 22.
You can transfer these functions to a derived class if you want to isolate the general-purpose list-handling features in a base class.
CMymfc16View Class
Listing 23 shows the code for the CMymfc16View class. This code will be carried over into the next two Modules.
MYMFC16VIEW.H // Mymfc16View.h : interface of the CMymfc16View class // //////////////////////////////////////////////////////////////////////
#if !defined(AFX_MYMFC16VIEW_H__4D011049_7E1C_11D0_8FE0_00C04FC2A0C2__INCLUDED_) #define AFX_MYMFC16VIEW_H__4D011049_7E1C_11D0_8FE0_00C04FC2A0C2__INCLUDED_
#if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000
class CMymfc16View : public CFormView { protected: POSITION m_position; // current position in document list CStudentList* m_pList; // copied from document
protected: // create from serialization only CMymfc16View(); DECLARE_DYNCREATE(CMymfc16View)
public: //{{AFX_DATA(CMymfc16View) enum { IDD = IDD_MYMFC16_FORM }; int m_nGrade; CString m_strName; //}}AFX_DATA
// Attributes public: CMymfc16Doc* GetDocument();
// Operations public:
// Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CMymfc16View) 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 ~CMymfc16View(); #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(CMymfc16View) 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 Mymfc16View.cpp inline CMymfc16Doc* CMymfc16View::GetDocument() { return (CMymfc16Doc*)m_pDocument; } #endif
//////////////////////////////////////////////////////////////////////
//{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations // immediately before the previous line.
#endif // !defined(AFX_MYMFC16VIEW_H__4D011049_7E1C_11D0_8FE0_00C04FC2A0C2__INCLUDED_)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
MYMFC16VIEW.CPP // Mymfc16View.cpp : implementation of the CMymfc16View class //
#include "stdafx.h" #include "mymfc16.h"
#include "Mymfc16Doc.h" #include "Mymfc16View.h"
#ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__ ; #endif
////////////////////////////////////////////////////////////////////// // CMymfc16View
IMPLEMENT_DYNCREATE(CMymfc16View, CFormView) BEGIN_MESSAGE_MAP(CMymfc16View, CFormView) //{{AFX_MSG_MAP(CMymfc16View) 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()
////////////////////////////////////////////////////////////////////// // CMymfc16View construction/destruction
CMymfc16View::CMymfc16View() : CFormView(CMymfc16View::IDD) { TRACE("Entering CMymfc16View constructor\n"); //{{AFX_DATA_INIT(CMymfc16View) m_nGrade = 0; m_strName = _T(""); //}}AFX_DATA_INIT m_position = NULL; }
CMymfc16View::~CMymfc16View() { }
void CMymfc16View::DoDataExchange(CDataExchange* pDX) { CFormView::DoDataExchange(pDX); //{{AFX_DATA_MAP(CMymfc16View) 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 CMymfc16View::PreCreateWindow(CREATESTRUCT& cs) { // TODO: Modify the Window class or styles here by modifying // the CREATESTRUCT cs return CFormView::PreCreateWindow(cs); }
void CMymfc16View::OnInitialUpdate() { TRACE("Entering CMymfc16View::OnInitialUpdate\n"); m_pList = GetDocument()->GetList(); CFormView::OnInitialUpdate(); }
////////////////////////////////////////////////////////////////////// // CMymfc16View diagnostics
#ifdef _DEBUG void CMymfc16View::AssertValid() const { CFormView::AssertValid(); }
void CMymfc16View::Dump(CDumpContext& dc) const { CFormView::Dump(dc); }
CMymfc16Doc* CMymfc16View::GetDocument() // non-debug version is inline { ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CMymfc16Doc))); return (CMymfc16Doc*)m_pDocument; } #endif //_DEBUG
////////////////////////////////////////////////////////////////////// // CMymfc16View message handlers
void CMymfc16View::OnClear() { TRACE("Entering CMymfc16View::OnClear\n"); ClearEntry(); }
void CMymfc16View::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) { // called by OnInitialUpdate and by UpdateAllViews TRACE("Entering CMymfc16View::OnUpdate\n"); m_position = m_pList->GetHeadPosition(); GetEntry(m_position); // initial data for view }
void CMymfc16View::OnStudentHome() { TRACE("Entering CMymfc16View::OnStudentHome\n"); // need to deal with list empty condition if (!m_pList->IsEmpty()) { m_position = m_pList->GetHeadPosition(); GetEntry(m_position); } }
void CMymfc16View::OnStudentEnd() { TRACE("Entering CMymfc16View::OnStudentEnd\n"); if (!m_pList->IsEmpty()) { m_position = m_pList->GetTailPosition(); GetEntry(m_position); } }
void CMymfc16View::OnStudentPrev() { POSITION pos; TRACE("Entering CMymfc16View::OnStudentPrev\n"); if ((pos = m_position) != NULL) { m_pList->GetPrev(pos); if (pos) { GetEntry(pos); m_position = pos; } } }
void CMymfc16View::OnStudentNext() { POSITION pos; TRACE("Entering CMymfc16View::OnStudentNext\n"); if ((pos = m_position) != NULL) { m_pList->GetNext(pos); if (pos) { GetEntry(pos); m_position = pos; } } }
void CMymfc16View::OnStudentIns() { TRACE("Entering CMymfc16View::OnStudentIns\n"); InsertEntry(m_position); GetDocument()->SetModifiedFlag(); GetDocument()->UpdateAllViews(this); }
void CMymfc16View::OnStudentDel() { // deletes current entry and positions to next one or head POSITION pos; TRACE("Entering CMymfc16View::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 CMymfc16View::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 CMymfc16View::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 CMymfc16View::OnUpdateStudentDel(CCmdUI* pCmdUI) { // called during idle processing and when Student menu drops down pCmdUI->Enable(m_position != NULL); }
void CMymfc16View::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 CMymfc16View::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 CMymfc16View::ClearEntry() { m_strName = ""; m_nGrade = 0; UpdateData(FALSE); ((CDialog*) this)->GotoDlgCtrl(GetDlgItem(IDC_NAME)); } |
Listing 23: The CMymfc16View class listing.
Testing the MYMFC16 Application
Build the program and start it from the debugger.
Figure 33: Running MYMFC16 program from the debugger. |
Figure 34: MYMFC16 program output in action.
Fill in the student name and grade fields, and then click the New button:
To insert the entry into the list. Repeat this action several times, using the Clear pushbutton to erase the data from the previous entry. Notice the toolbar buttons enable/disable change. When you exit the application, the debug output should look similar to this:
...
Entering CMymfc16View::OnStudentIns
Entering CMymfc16View::OnClear
Entering CMymfc16View::OnStudentIns
Entering CMymfc16View::OnClear
Entering CMymfc16View::OnStudentIns
Entering CMymfc16View::OnClear
Entering CMymfc16View::OnStudentIns
Entering CMymfc16View::OnClear
a CMymfc16Doc at $4216B0
m_strTitle = Untitled
m_strPathName =
m_bModified = 1
m_pDocTemplate = $4218C0
a CObList at $421704
with 4 elements
a CStudent at $422DD0
m_strName = Mr. Pink Panther
m_nGrade = 95
a CStudent at $422340
m_strName = Mr. Bush Blair
m_nGrade = 40
a CStudent at $422460
m_strName = Mrs. Rice Plate
m_nGrade = 67
a CStudent at $422200
m_strName = Mr. Mechanick
m_nGrade = 88
Warning: destroying an unsaved document.
The thread 0x5B8 has exited with code 0 (0x0).
The program 'F:\mfcproject\mymfc16\Debug\mymfc16.exe' has exited with code 0 (0x0).
You can clear all data by using the Edit, Clear All menu.
Figure 35: Deleting all the data using the Edit Clear All menu.
Two Exercises for the Learners
You might have noticed the absence of a Modify button on the toolbar. Without such a button, you can't modify an existing student record. Can you add the necessary toolbar button and message handlers? The most difficult task might be designing a graphic for the button's tile. Recall that the CMymfc16View class is just about ready to be a general-purpose base class. Try separating the CStudent-specific virtual functions into a derived class. After that, make another derived class that uses a new element class other than CStudent.
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.