Programming Microsoft Visual C++
The application framework does most of the work for printing and print preview. To use the printer effectively, you must understand the sequence of function calls and know which functions to override.
The Printer Device Context and the CView::OnDraw Function
When your program prints on the printer, it uses a device context object of class CDC. Don't worry about where the object comes from; the application framework constructs it and passes it as a parameter to your view's OnDraw function. If your application uses the printer to duplicate the display, the OnDraw function can do double duty. If you're displaying, the OnPaint function calls OnDraw and the device context is the display context. If you're printing, OnDraw is called by another CView virtual function, OnPrint, with a printer device context as a parameter. The OnPrint function is called once to print an entire page.
In print preview mode, the OnDraw parameter is actually a pointer to a CPreviewDC object. Your OnPrint and OnDraw functions work the same regardless of whether you're printing or previewing.
The CView::OnPrint Function
You've seen that the base class OnPrint function calls OnDraw and that OnDraw can use both a display device context and a printer device context. The mapping mode should be set before OnPrint is called. You can override OnPrint to print items that you don't need on the display, such as a title page, headers, and footers. The OnPrint parameters are as follows:
- A pointer to the device context
- A pointer to a print information object (CPrintInfo) that includes page dimensions, the current page number, and the maximum page number
In your overridden OnPrint function, you can elect not to call OnDraw at all to support print logic that is totally independent of the display logic. The application framework calls the OnPrint function once for each page to be printed, with the current page number in the CPrintInfo structure. You'll soon find out how the application framework determines the page number.
Preparing the Device ContextThe CView::OnPrepareDC Function
If you need a display mapping mode other than MM_TEXT (and you often do), that mode is usually set in the view's OnPrepareDC function. You override this function yourself if your view class is derived directly from CView, but it's already overridden if your view is derived from CScrollView. The OnPrepareDC function is called in OnPaint immediately before the call to OnDraw. If you're printing, the same OnPrepareDC function is called, this time immediately before the application framework calls OnPrint. Thus, the mapping mode is set before both the painting of the view and the printing of a page.
The second parameter of the OnPrepareDC function is a pointer to a CPrintInfo structure. This pointer is valid only if OnPrepareDC is being called prior to printing. You can test for this condition by calling the CDC member function IsPrinting. The IsPrinting function is particularly handy if you're using OnPrepareDC to set different mapping modes for the display and the printer.
If you do not know in advance how many pages your print job requires, your overridden OnPrepareDC function can detect the end of the document and reset the m_bContinuePrinting flag in the CPrintInfo structure. When this flag is FALSE, the OnPrint function won't be called again and control will pass to the end of the print loop.
The Start and End of a Print Job
When a print job starts, the application framework calls two CView functions, OnPreparePrinting and OnBeginPrinting. (AppWizard generates the OnPreparePrinting, OnBeginPrinting, and OnEndPrinting functions for you if you select the Printing And Print Preview option.) The first function, OnPreparePrinting, is called before the display of the Print dialog. If you know the first and last page numbers, call CPrintInfo::SetMinPage and CPrintInfo::SetMaxPage in OnPreparePrinting. The page numbers you pass to these functions will appear in the Print dialog for the user to override.
The second function, OnBeginPrinting, is called after the Print dialog exits. Override this function to create Graphics Device Interface (GDI) objects, such as fonts, that you need for the entire print job. A program runs faster if you create a font once instead of re-creating it for each page.
The CView function OnEndPrinting is called at the end of the print job, after the last page has been printed. Override this function to get rid of GDI objects created in OnBeginPrinting.
The following table summarizes the important overridable CView print loop functions.
Function | Common Override Behavior |
OnPreparePrinting | Sets first and last page numbers |
OnBeginPrinting | Creates GDI objects |
OnPrepareDC (for each page) | Sets mapping mode and optionally detects end of print job |
OnPrint | Does print-specific output and then calls OnDraw (for each page) |
OnEndPrinting | Deletes GDI objects |