List - worked example
key : purple - original code / blue - new code
Step 1 :
Continue with the program names - simpy edit the previous code. This task uses a POSITION to allow both views access to the list of names. As a result, all of the Get and Set functions previously in the Document should be removed. The pointer to the CName class should also be removed.
Step 2 :
Include the afxtempl library in the Document to allow the CTypedPtrList feature to be used :
#include <afxtempl.h>
Step 3 :
Define the CTypedPtrList and the POSITION (both private access) :
private:
// define the CTypedPtrList m_NameList
CTypedPtrList<CPtrList, CName*> m_NameList;
// define
the location of the current item in the list
POSITION m_nCurrentPosition;
Step 4 :
Create a GetCurrentItem() function within the Document (public access) :
CName*
CNamesDoc::GetCurrentItem()
{
if(m_nCurrentPosition!=NULL)
{return m_NameList.GetAt(m_nCurrentPosition);
}
else
{return NULL;
}
}
Step 5 :
Edit the AddItems() function within the Document :
void
CNamesDoc::AddNames()
{
CEnterNamesDlg dlg;
if(dlg.DoModal() == IDOK)
{CName* temp = new CName(dlg.m_strFirstName, dlg.m_strSecondName);
m_NameList.AddTail(temp);
m_nCurrentPosition = m_NameList.GetTailPosition();
UpdateAllViews( NULL );}
}
Step 6 :
Edit the OnDraw() function within the FormView :
void
CFormNameView::OnDraw(CDC* pDC)
{
CName * pName = ((CNamesDoc*)m_pDocument)->GetCurrentItem();
if(pName != NULL)
{m_strFirstName = pName->GetFirstName();
m_strSecondName = pName->GetSecondName();}
else
{m_strFirstName = "";
m_strSecondName = "";}
UpdateData(FALSE);
}
Step 7 :
To allow the list to be displayed a GetNextItem() and a GetHeadPosition() function must be added to the Document (both public access) :
CName*
CNamesDoc::GetNextItem(POSITION &pos)
{
return m_NameList.GetNext( pos );
}
POSITION
CNamesDoc::GetHeadPosition()
{
return m_NameList.GetHeadPosition();
}
Step 8 :
The OnDraw() function in the standard view must be edited to display the list :
void
CNamesView::OnDraw(CDC* pDC)
{
CNamesDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
TEXTMETRIC tm;
pDC->GetTextMetrics( &tm );
int nLineHeight = tm.tmHeight + tm.tmExternalLeading;
CPoint ptText( 0, 0 );
POSITION pos;
pos = ((CNamesDoc*)m_pDocument)->GetHeadPosition();
while(pos!=NULL)
{CName * pName = ((CNamesDoc*)m_pDocument)->GetNextItem(pos);
pDC->TextOut(ptText.x, ptText.y, pName->GetFullName());
ptText.y += nLineHeight;}
}
Step 9 :
Finally add the following code to the destructor to avoid memory leaks from the newly created pointers :
CNamesDoc::~CNamesDoc()
{
POSITION pos = m_NameList.GetHeadPosition();
while( pos != NULL )
{delete m_NameList.GetNext( pos );
}
}
Note : The Cancel button within the Enter Names Dialog may be removed and the OK button may be renamed Add.
Click here for the basic exercise
Click here for the source code
Click here to return to menu