⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 apc.htm

📁 有关Visual C++ 6.0 编程实例与技巧方面的相关资料
💻 HTM
📖 第 1 页 / 共 4 页
字号:
<P>As I mentioned earlier, the code in Listing C.4 works fine, but there is a betterway to allocate the resources needed. Currently every time a page is printed, OnPrint()is called to draw the page, and all the resources are created from scratch. Thatprobably won't slow things down too much for this simple output, but in a large,complex report you might want to set up a number of resources and other calculationsjust once at the start of the report. Then you can print a number of pages and cleanup the resources at the end of the report.</P><P>The OnBeginPrinting()virtual function is an ideal place to do this initialization,and its sister function, OnEndPrinting(), is the place to clean up these resources.OnBeginPrinting() is called after OnPreparePrinting() and is the first place wherea printer device context is passed in. This device context is the one that is usedduring the printing process, so you can set up all the GDI objects and printer pagecoordinates at this point. The default code supplied automatically by the ClassWizardjust gives you an empty function:</P><P><PRE>void CPrintItView::OnBeginPrinting(CDC* /*pDC*/, &Acirc; CPrintInfo* /*pInfo*/){    // TODO: add extra initialization before printing}</PRE><P>Take a close look at that function definition. Notice the parameters are actuallycommented out to the compiler, throwing warning messages about unused parameterswhen you compile. You'll have to remember to uncomment these parameters before youstart using them.</P><P>You can now add the GDI object creation calls to this function to avoid doingit on every page:</P><P><PRE>m_fnTimes.CreatePointFont(720,&quot;Times New Roman&quot;,pDC);m_brHatch.CreateHatchBrush(HS_CROSS,RGB(64,64,64));</PRE><P>Notice that the fnTimes and brHatch objects have been prefixed by an m_; thisis a naming convention to indicate that the objects have class scope (are embeddedin the class) rather than local scope (are embedded in the function). Because you'llneed to access these GDI objects in OnPrint(), you can add them to the class declaration.You can do this by adding the font and brush objects to the class declaration likethis:</P><P><PRE>protected:    CFont     m_fnTimes;    CBrush    m_brHatch;</PRE><P>You can add these either by double-clicking the CPrintItView class in the ClassViewand adding them directly or by using the Add Member Variable dialog box.</P><P>Also notice that the hatched brush is created with the CreateHatchBrush() functionrather than with the constructor. This is because the brush will exist as long asthe view does, but you must call DeleteObject() in the OnBeginPrinting() functionso that the underlying GDI resource is freed between prints. You can add the codeto delete both the font and brush GDI objects in OnEndPrinting(), as shown in theselines:</P><P><PRE>m_fnTimes.DeleteObject();m_brHatch.DeleteObject();</PRE><P>All that remains is to remove the local GDI objects from the OnPrint() functionitself and replace their references with the member variable versions. You can dothis by replacing the CFont fnTimes and CBrush brHatch local variables and theircreation functions and just selecting the precreated font and brush:</P><P><PRE>CFont* pOldFont = (CFont*)pDC-&gt;SelectObject(&amp;m_fnTimes);CBrush* pOldBrush = (CBrush*)pDC-&gt;SelectObject(&amp;m_brHatch);</PRE><P>If you were to build and run the application after making these changes, you'dprobably notice no difference. Functionally it's the same, but the print and previewshould be a little faster. If you had a large, complex 100-page report using lotsof GDI resources, you'd definitely find this technique useful in speeding up theprinting.</P><BLOCKQUOTE>	<P><HR><B>USING COORDINATES FROM </B>OnBeginPrinting()</P>	<P>You might be tempted to also store the coordinates from OnBeginPrinting(). This	won't work because CPrintInfo's m_rectDraw member hasn't been initialized by that	stage and random coordinates will be used.<HR></BLOCKQUOTE><H3><A NAME="Heading12"></A>Customizing Device Context Preparation</H3><P>Before both OnDraw() and OnPrint() are called, the OnPrepareDC() virtual functionis called and can be overridden in your view class to perform any device contextmodifications that might be common to both OnDraw() and OnPrint(). You might wantto set mapping modes or set certain common draw modes to the device context for bothonscreen and printing modes. The override isn't supplied by the AppWizard, but caneasily be added from the Add Virtual Function dialog box. One thing common to bothOnDraw() and OnPrint() in the example is the SetTextAlign() device context function.You could add this to an OnPrepareDC() function like this:</P><P><PRE>void CPrintItView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo){    pDC-&gt;SetTextAlign(TA_CENTER+TA_BASELINE);}</PRE><P>There might be times, especially when preparing WYSIWYG printouts, that it isadvantageous to set mapping modes and window extents in a common function beforethe draw or print function is called. OnPrepareDC() is the place to put any devicecontext-specific initialization code.</P><P><H3><A NAME="Heading13"></A>Aborting the Print Job</H3><P>Another use of OnPrepareDC() is to call printer escapes or other print document-specificfunctions. If you had a particularly long report, you might want to give the userthe option of terminating the printing process and aborting the print. The AbortDoc()device context function aborts the printing document for a printer device context.You can try this by adding the following lines to OnPrepareDC() and aborting thedocument after three pages:</P><P><PRE>if (pDC-&gt;IsPrinting())    if (pInfo-&gt;m_nCurPage==3) pDC-&gt;AbortDoc();</PRE><H2><A NAME="Heading14"></A>Direct Printing Without the Framework</H2><P>So far in this chapter, I've shown you the SDI and MDI framework support for printing.This support melds nicely into the Document/View architecture, but there are timeswhen you just want quick and easy access to a printer or don't have the frameworkavailable--in a dialog-based application, for example.</P><P>The framework support hides lower-level printing support that is the bedrock forall the printing operations. This section explains how this support works and showsit in use in a dialog box-based application example.</P><P><H3><A NAME="Heading15"></A>Invoking the Print Dialog Box Directly</H3><P>You saw in the earlier section &quot;Using the Print Dialog Box&quot; how theCPrintDialog class provides a wrapper for the common PRINTDLG dialog and how thiswas called from CView::DoPreparePrinting().</P><P>The same dialog box and class can be used directly to set up the destination printerand its default settings just like you'd use a normal modal dialog box. You can usethe same access functions to set the page numbers and copy defaults as you used frominside the framework's DoPreparePrinting() function.</P><P>Listing C.7 shows this dialog box being used directly to configure the printerfor dialog box-based printing and then prints a small document from the defaultsset by the dialog box.</P><P>The direct printing mechanism works via the StartDoc() and EndDoc() functionsshown in this listing and is explained in the next section.</P><P>You can use the AppWizard to create a dialog box-based application named DlgPrintand create an OnOK() handler with the ClassWizard to implement the printing code,as shown in Listing C.7.</P><P><H4>LISITNG C.7.&nbsp;&nbsp;LST23_7.CPP--IMPLEMENTING A DIRECT DOCUMENT PRINT INOnOK OF A DIALOG BOX-BASED APPLICATION.</H4><PRE>1:  void CDlgPrintDlg::OnOK()2:  {3:      // TODO: Add extra validation here4:5:      // ** Construct a CPrintDialog object6:      CPrintDialog dlgPrint(FALSE,PD_ALLPAGES,this);7:8:      if (dlgPrint.DoModal()==IDOK)9:      {10:          // ** Attach the printer DC from the dialog11:          // ** to a CDC object12:          CDC dcPrint;13:          dcPrint.Attach(dlgPrint.GetPrinterDC());14:15:          // ** Create and fill a DOCINFO structure16:          DOCINFO myPrintJob;17:          myPrintJob.cbSize = sizeof(myPrintJob);18:          myPrintJob.lpszDocName = &quot;MyPrintJob&quot;;19:          myPrintJob.lpszOutput = NULL;20:          myPrintJob.lpszDatatype = NULL;21:          myPrintJob.fwType = NULL;22:23:          // ** Start the printing document24:          if (dcPrint.StartDoc(&amp;myPrintJob)&gt;=0)25:          {26:              // ** Start a page27:              dcPrint.StartPage();28:29:              // ** Start drawing30:              dcPrint.TextOut(0,0,&quot;My Small Print Job&quot;);31:32:              // ** Throw the page33:              dcPrint.EndPage();34:35:              // ** Close the document36:              dcPrint.EndDoc();37:          }38:39:          // ** Delete the printer device context40:          dcPrint.DeleteDC();41:      }42:43:      // ** Carry on with the standard OnOK44:      CDialog::OnOK();45:  }</PRE><P>Listing C.7 declares a CPrintDialog object dlgPrint at line 6 that takes threeparameters in its constructor. The first parameter is a flag that can be set as TRUEto display the Print Setup dialog box, or FALSE to display the Print dialog box.The second parameter is a set of combinable flags that customize the settings ofthe dialog box (too numerous to cover here). The third parameter is a pointer tothe parent window; in this case the C++ this pointer indicates that the dialog boxis the parent.</P><P>On line 8, dlgPrint.DoModal()is called to display this dialog box. If the userclicks OK, the print begins; otherwise, the block is skipped.</P><P>When the user has clicked OK in the Print dialog box, a device context for theprinter is created and attached to a CDC object in line 13 to make it easier to use.You must remember to delete the device context itself, as shown in line 40.</P><P>You can add the listing lines and handler, build and run it, and click OK of thedialog box application to run the new code.</P><P><H3><A NAME="Heading16"></A>Using StartDoc() and EndDoc()</H3><P>The CDC device context has many printer-specific functions. To start a new print,Windows must create a spool document to store the print job and submit it to theprinter when it is complete. The StartDoc() function tells Windows to start spooling,and the EndDoc() function tells it that the document is complete and can be sentto the printer. You saw the AbortDoc() function earlier that will abort the printand cancel the print job rather than send to the printer.</P><P>Listing C.7 calls the StartDoc() member of the printer device context object dcPrintat line 24, passing a pointer to a DOCINFO structure. This structure holds the detailsof the print job. The only detail you must specify is a name for the spool document,which is assigned at line 18. Notice that it has an unusual cbSize member that holdsthe size of the structure. This is assigned the value from sizeof(myPrintJob) atline 17. You see this sort of strange action going on a lot at the Win32 API levelbecause DOCINFO is an old C-style structure; the cbSize is used because there area few different forms of DOCINFO and the only way to tell them apart is the size.</P><P>When StartDoc() is called, it will try to start the print job and return a positivevalue if it succeeds. There are many reasons why it might fail, such as low diskspace or memory, or a corrupt printer driver, so it's a good idea to carry on withthe print only after checking the return code.</P><P>After the document is printed, you should call EndDoc() as shown on line 36 tostart printing the document.</P><BLOCKQUOTE>	<P><HR><B>WATCHING THE WINDOWS SPOOLER</B></P>	<P>You can watch the print document as it builds up by placing a breakpoint in the	OnPrint() function or after a StartDoc() function and opening your printer status	icon from the Printers group available from the main Windows Start menu under the	Settings option.<HR></BLOCKQUOTE><H3><A NAME="Heading17"></A>Using StartPage() and EndPage()</H3><P>Another pair of printer device context functions are StartPage() and EndPage().The StartPage() function is used to initialize the device context ready for printinga new page. This will reset some of the device context settings such as the currentgraphics cursor position and set the document spooling information for starting anew page.</P><P>Typically, you'd call StartPage(), do some drawing in the device context for thedetails to be printed on that page, and call EndPage() to write the page away tothe spool file to add it to the print document.</P><P>In Listing C.7, StartPage() is called on line 27, followed by a solitary TextOut()function to draw something on the printer page, followed by a call to EndPage() online 33.</P><P>When EndPage() is called, the special printer codes for throwing a Form Feed aresent to the spooler and the spool document registers another print page. You canrepeat this StartPage() and EndPage() sequence for all the document pages beforecalling EndDoc() to complete the printing process. You can use the printer devicecontext for drawing in just the same way as the OnPrint() was used in the SDI applicationin between the StartPage() and EndPage() calls. The same functions were called inthe SDI framework, but the framework hides it from you, only calling your OnPrint()between start and end page calls.</P><H1></H1><CENTER><P><HR><A HREF="../apb/apb.htm"><IMG SRC="../button/previous.gif" WIDTH="128" HEIGHT="28"ALIGN="BOTTOM" ALT="Previous chapter" BORDER="0"></A><A HREF="../apd/apd.htm"><IMGSRC="../button/next.gif" WIDTH="128" HEIGHT="28" ALIGN="BOTTOM" ALT="Next chapter"BORDER="0"></A><A HREF="../index.htm"><IMG SRC="../button/contents.gif" WIDTH="128"HEIGHT="28" ALIGN="BOTTOM" ALT="Contents" BORDER="0"></A> <BR><BR></P><P>&copy; <A HREF="../copy.htm">Copyright</A>, Macmillan Computer Publishing. Allrights reserved.</CENTER></BODY></HTML>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -