[ Home | Syllabus | Course Notes | Assignments | Search]
Objectives of studying this exercise: (source code here)
Iteration
GetHeadPosition | Returns the position of the head element of the list. |
GetTailPosition | Returns the position of the tail element of the list. |
GetNext | Gets the next element for iterating. |
GetPrev | Gets the previous element for iterating. |
CObject*& GetNext( POSITION& rPosition );
// updates rPosition to next position
// can use pointer returned to modify object in list
CObject* GetNext( POSITION& rPosition ) const;
// in Student.h
typedef CTypedPtrList<CObList, CStudent*> CStudentList; // A list of CStudent objects built on CObList - type safe use of template class CTypedPtrList
// in StuDoc.h private: CStudentList m_studentList;
// for access to list (used by view object) public: CStudentList* GetList() { return &m_studentList; }
void CStudentView::OnInitialUpdate() { m_pList = GetDocument()->GetList(); // remember the list CFormView::OnInitialUpdate(); }
void CStudentView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint) { // called by OnInitialUpdate and by UpdateAllViews m_position = m_pList->GetHeadPosition(); GetEntry(m_position); // initial data for view }
void CStudentView::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 CStudentView::OnStudentIns() { InsertEntry(m_position); GetDocument()->SetModifiedFlag(); GetDocument()->UpdateAllViews(this); } void CStudentView::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 CStudentView::OnStudentDel() { // deletes current entry and positions to next one or head POSITION pos; if ((pos = m_position) != NULL) { // how good is your c++ m_pList->GetNext(pos); // iterate to next position (updates pos) if (pos == NULL) { // at end - set position to head pos = m_pList->GetHeadPosition(); if (pos == m_position) { // deleting only element in list pos = NULL; } } GetEntry(pos); // load data from new current position CStudent* ps = m_pList->GetAt(m_position); // remember so ca delete later m_pList->RemoveAt(m_position); // remove from list delete ps; // prevent memory leak m_position = pos; // set new position GetDocument()->SetModifiedFlag(); GetDocument()->UpdateAllViews(this); } }
Message handlers for navigation buttons/menu items:
void CStudentView::OnStudentHome() { // need to deal with list empty condition if (!m_pList->IsEmpty()) { m_position = m_pList->GetHeadPosition(); GetEntry(m_position); } } void CStudentView::OnStudentEnd() { if (!m_pList->IsEmpty()) { m_position = m_pList->GetTailPosition(); GetEntry(m_position); } } void CStudentView::OnStudentPrev() { POSITION pos; if ((pos = m_position) != NULL) { m_pList->GetPrev(pos); if (pos) { GetEntry(pos); m_position = pos; } } } void CStudentView::OnStudentNext() { POSITION pos; if ((pos = m_position) != NULL) { m_pList->GetNext(pos); if (pos) { GetEntry(pos); m_position = pos; } } }
void CStudentView::ClearEntry() { m_strName = ""; m_nGrade = 0; UpdateData(FALSE); // invok DDX to clear form elements ((CDialog*) this)->GotoDlgCtrl(GetDlgItem(IDC_NAME)); // set focus to dialog item whose id is IDC_NAME }
protected: // control bar embedded members CStatusBar m_wndStatusBar; CToolBar m_wndToolBar;
Toolbar/Status created here
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) { if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1; if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) || !m_wndToolBar.LoadToolBar(IDR_MAINFRAME)) { return -1; // fail to create } if (!m_wndStatusBar.Create(this) || !m_wndStatusBar.SetIndicators(indicators, sizeof(indicators)/sizeof(UINT))) { return -1; // fail to create } // TODO: Delete these three lines if you don't want the toolbar to // be dockable m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY); EnableDocking(CBRS_ALIGN_ANY); DockControlBar(&m_wndToolBar); return 0; }
When using CObList - call its serialize
It will call serialize of each object using polymorphism to call correct one
It also marks length of list somehow so you can store other objects after list and can read in OK
void CStudentDoc::Serialize(CArchive& ar) { m_studentList.Serialize(ar); }
Add Serialize override to CStudent object
void CStudent::Serialize(CArchive& ar) { if (ar.IsStoring()) { ar << m_strName << m_nGrade; } else { ar >> m_strName >> m_nGrade; } }