Windows NT Systems Programming: Spring 2000

[ Home | Syllabus | Course Notes | Assignments | Search]


Handling a List of Students: EX17a

Objectives of studying this exercise: (source code here)


Collection Objects

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;


A List of Students

// 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;
    }

View Accesses List

void CStudentView::OnInitialUpdate()
{
    m_pList = GetDocument()->GetList(); // remember the list
	CFormView::OnInitialUpdate();
}
rainbow.gif (2243 bytes)
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	
}
rainbow.gif (2243 bytes)
void CStudentView::GetEntry(POSITION position) hptrd_left.gif (955 bytes)
{
    if (position) {
        CStudent* pStudent = m_pList->GetAt(position); hptrd_left.gif (955 bytes)
        m_strName = pStudent->m_strName;
        m_nGrade = pStudent->m_nGrade;
    }
    else {
        ClearEntry();
    }
    UpdateData(FALSE); hptrd_left.gif (955 bytes)
}
rainbow.gif (2243 bytes)

rainbow.gif (2243 bytes)

Inserting new Student into document

void CStudentView::OnStudentIns() hptrd_left.gif (955 bytes)
{
    InsertEntry(m_position);
    GetDocument()->SetModifiedFlag();hptrd_left.gif (955 bytes)
    GetDocument()->UpdateAllViews(this); hptrd_left.gif (955 bytes)
	
}
void CStudentView::InsertEntry(POSITION position)
{
    if (UpdateData(TRUE)) { hptrd_left.gif (955 bytes)
        // UpdateData returns FALSE if it detects a user error
        CStudent* pStudent = new CStudent; hptrd_left.gif (955 bytes)
        pStudent->m_strName = m_strName;
        pStudent->m_nGrade = m_nGrade;
        m_position = m_pList->InsertAfter(m_position, pStudent);hptrd_left.gif (955 bytes)
    }
}
rainbow.gif (2243 bytes)

rainbow.gif (2243 bytes)

Deleting a Student from the List

void CStudentView::OnStudentDel() hptrd_left.gif (955 bytes)
{
    // 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);
    }
	
}

Navigating in the List

Message handlers for navigation buttons/menu items:
rainbow.gif (2243 bytes)

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;
        }
    }
	
}
rainbow.gif (2243 bytes)
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
}

Hooking up the Navigation ToolBar

Toolbar/Status created here

rainbow.gif (2243 bytes)
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))hptrd_left.gif (955 bytes)
	{
		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); hptrd_left.gif (955 bytes)
	EnableDocking(CBRS_ALIGN_ANY);
	DockControlBar(&m_wndToolBar);

	return 0;
}
rainbow.gif (2243 bytes)

Serializing

void CStudentDoc::Serialize(CArchive& ar)
{
    m_studentList.Serialize(ar);
}
void CStudent::Serialize(CArchive& ar)
{
    if (ar.IsStoring()) {
        ar << m_strName << m_nGrade;
    }
    else {
        ar >> m_strName >> m_nGrade;
    }
}

Copyright chris wild 1999/2000.
For problems or questions regarding this web contact [Dr. Wild].
Last updated: February 02, 2000.