The Ex17b Example: A Multi-Page Print Program
In this example, the document contains an array of 50 CRect objects that define circles. The circles are randomly positioned in a 6-by-6-inch area and have random diameters of as much as 0.5 inch. The circles, when drawn on the display, look like two-dimensional simulations of soap bubbles. Instead of drawing the circles on the printer, the application prints the corresponding CRect coordinates in numeric form, 12 to a page, with headers and footers. Here are the steps:
Run the MFC Application Wizard to generate a project named Ex17b. Select Single Document, and accept the defaults for all the other settings.
Edit the

#include <afxtempl.h>
Edit the

typedef CArray<CRect, CRect&> CRectArray;
Next, add the following public data members to the

public:
enum { nLinesPerPage = 12 };
enum { nMaxEllipses = 50 };
CRectArray m_ellipseArray;
The two enumerations are object-oriented replacements for #defines.
Edit the

BOOL CEx17bDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
int n1, n2, n3;
// Make 50 random circles
srand((unsigned) time(NULL));
m_ellipseArray.SetSize(nMaxEllipses);
for (int i = 0; i < nMaxEllipses; i++) {
n1 = rand() * 600 / RAND_MAX;
n2 = rand() * 600 / RAND_MAX;
n3 = rand() * 50 / RAND_MAX;
m_ellipseArray[i] = CRect(n1, -n2, n1 + n3, -(n2 + n3));
}
return TRUE;
}
void CEx17bDoc::Serialize(CArchive& ar)
{
m_ellipseArray.Serialize(ar);
}
Edit the


public:
int m_nPage;
private:
void PrintPageHeader(CDC *pDC);
void PrintPageFooter(CDC *pDC);
The m_nPage data member holds the document's current page number for printing. The private functions are for the header and footer subroutines.
Edit the OnDraw function in

void CEx17bView::OnDraw(CDC* pDC)
{
int i, j;
CEx17bDoc* pDoc = GetDocument();
j = pDoc->m_ellipseArray.GetUpperBound();
for (i = 0; i < j; i++) {
pDC->Ellipse(pDoc->m_ellipseArray[i]);
}
}
Insert the OnPrepareDC function in

void CEx17bView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
pDC->SetMapMode(MM_LOENGLISH);
}
Insert the OnPrint function in

void CEx17bView::OnPrint(CDC* pDC, CPrintInfo* pInfo)
{
int i, nStart, nEnd, nHeight;
CString str;
CPoint point(720, -1440);
CFont font;
TEXTMETRIC tm;
pDC->SetMapMode(MM_TWIPS);
CEx17bDoc* pDoc = GetDocument();
m_nPage = pInfo->m_nCurPage; // for PrintPageFooter's benefit
nStart = (m_nPage - 1) * CEx17bDoc::nLinesPerPage;
nEnd = nStart + CEx17bDoc::nLinesPerPage;
// 14-point fixed-pitch font
font.CreateFont(-280, 0, 0, 0, 400, FALSE, FALSE,
0, ANSI_CHARSET, OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_MODERN, "Courier New");
// Courier New is a TrueType font
CFont* pOldFont = (CFont*) (pDC->SelectObject(&font));
PrintPageHeader(pDC);
pDC->GetTextMetrics(&tm);
nHeight = tm.tmHeight + tm.tmExternalLeading;
for (i = nStart; i < nEnd; i++) {
if (i > pDoc->m_ellipseArray.GetUpperBound()) {
break;
}
str.Format("%6d %6d %6d %6d %6d", i + 1,
pDoc->m_ellipseArray[i].left,
pDoc->m_ellipseArray[i].top,
pDoc->m_ellipseArray[i].right,
pDoc->m_ellipseArray[i].bottom);
point.y -= nHeight;
pDC->TextOut(point.x, point.y, str);
}
PrintPageFooter(pDC);
pDC->SelectObject(pOldFont);
}
Edit the OnPreparePrinting function in

BOOL CEx17bView::OnPreparePrinting(CPrintInfo* pInfo)
{
CEx17bDoc* pDoc = GetDocument();
pInfo->SetMaxPage(pDoc->m_ellipseArray.GetUpperBound() /
CEx17bDoc::nLinesPerPage + 1);
return DoPreparePrinting(pInfo);
}
Insert the page header and footer functions in

void CEx17bView::PrintPageHeader(CDC* pDC)
{
CString str;
CPoint point(0, 0);
pDC->TextOut(point.x, point.y, "Bubble Report");
point += CSize(720, -720);
str.Format("%6.6s %6.6s %6.6s %6.6s %6.6s",
"Index", "Left", "Top", "Right", "Bottom");
pDC->TextOut(point.x, point.y, str);
}
void CEx17bView::PrintPageFooter(CDC* pDC)
{
CString str;
CPoint point(0, -14400); // Move 10 inches down
CEx17bDoc* pDoc = GetDocument();
str.Format("Document %s", (LPCSTR) pDoc->GetTitle());
pDC->TextOut(point.x, point.y, str);
str.Format("Page %d", m_nPage);
CSize size = pDC->GetTextExtent(str);
point.x += 11520 - size.cx;
pDC->TextOut(point.x, point.y, str); // right-justified
}
Build and test the application. For one set of random numbers, the bubble view window looks like this:

Each time you choose New from the File menu, you should see a different picture. In Print Preview, the first page of the output should look like this:

In the Print dialog box, you can specify any range of pages to print.