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.
#include <afxtempl.h>
typedef CArray<CRect, CRect&> CRectArray;
Next add the following public data members to the ex19bDoc.h header file:
public: enum { nLinesPerPage = 12 }; enum { nMaxEllipses = 50 }; CRectArray m_ellipseArray;
The two enumerations are object-oriented replacements for #defines.
BOOL CEx19bDoc::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 CEx19bDoc::Serialize(CArchive& ar) { m_ellipseArray.Serialize(ar); }
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.
void CEx19bView::OnDraw(CDC* pDC) { int i, j; CEx19bDoc* pDoc = GetDocument(); j = pDoc->m_ellipseArray.GetUpperBound(); for (i = 0; i < j; i++) { pDC->Ellipse(pDoc->m_ellipseArray[i]); } }
void CEx19bView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo) { pDC->SetMapMode(MM_LOENGLISH); }
void CEx19bView::OnPrint(CDC* pDC, CPrintInfo* pInfo) { int i, nStart, nEnd, nHeight; CString str; CPoint point(720, -1440); CFont font; TEXTMETRIC tm; pDC->SetMapMode(MM_TWIPS); CEx19bDoc* pDoc = GetDocument(); m_nPage = pInfo->m_nCurPage; // for PrintPageFooter's benefit nStart = (m_nPage - 1) * CEx19bDoc::nLinesPerPage; nEnd = nStart + CEx19bDoc::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); }
BOOL CEx19bView::OnPreparePrinting(CPrintInfo* pInfo) { CEx19bDoc* pDoc = GetDocument(); pInfo->SetMaxPage(pDoc->m_ellipseArray.GetUpperBound() / CEx19bDoc::nLinesPerPage + 1); return DoPreparePrinting(pInfo); }
void CEx19bView::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 CEx19bView::PrintPageFooter(CDC* pDC) { CString str; CPoint point(0, -14400); // Move 10 inches down CEx19bDoc* 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 }
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.
With the Print dialog, you can specify any range of pages to print.