📄 apc.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN"><HTML><HEAD> <META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1"><SCRIPT LANGUAGE="JavaScript"><!--function popUp(pPage) { var fullURL = document.location; var textURL = fullURL.toString(); var URLlen = textURL.length; var lenMinusPage = textURL.lastIndexOf("/"); lenMinusPage += 1; var fullPath = textURL.substring(0,lenMinusPage); popUpWin = window.open('','popWin','resizable=yes,scrollbars=no,width=525,height=394'); figDoc= popUpWin.document; zhtm= '<HTML><HEAD><TITLE>' + pPage + '</TITLE>'; zhtm += '</head>'; zhtm += '<BODY bgcolor="#FFFFFF">'; zhtm += '<IMG SRC="' + fullPath + pPage + '">'; zhtm += '<P><B>' + pPage + '</B>'; zhtm += '</BODY></HTML>'; window.popUpWin.document.write(zhtm); window.popUpWin.document.close(); // Johnny Jackson 4/28/98 }//--> </SCRIPT><link rel="stylesheet" href="/includes/stylesheets/ebooks.css"> <META NAME="GENERATOR" Content="Symantec Visual Page Mac 1.1.1"> <TITLE>Teach Yourself Visual C++ 6 in 21 Days -- Appendix C -- Printing and Print Previewing</TITLE></HEAD><BODY TEXT="#000000" BGCOLOR="#FFFFFF"><H1 ALIGN="CENTER"><IMG SRC="../button/sams.gif" WIDTH="171" HEIGHT="66" ALIGN="BOTTOM"BORDER="0"><BR>Teach Yourself Visual C++ 6 in 21 Days</H1><CENTER><P><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> <HR></CENTER><H1 ALIGN="CENTER">- C -<BR>Printing and Print Previewing</H1><H1></H1><UL> <LI><A HREF="#Heading1">Using the Framework's Functionality</A> <UL> <LI><A HREF="#Heading2">Using Default Print Functionality</A> <LI><A HREF="#Heading4">Overriding OnPrint()</A> <LI><A HREF="#Heading5">Using the Printer Device Context</A> <LI><A HREF="#Heading6">Maintaining the Aspect Ratio</A> </UL> <LI><A HREF="#Heading7">Pagination and Orientation</A> <UL> <LI><A HREF="#Heading8">Setting the Start and End Pages</A> <LI><A HREF="#Heading9">Using the Print Dialog Box</A> <LI><A HREF="#Heading10">Using Portrait and Landscape Orientations</A> <LI><A HREF="#Heading11">Adding GDI Objects with OnBeginPrinting()</A> <LI><A HREF="#Heading12">Customizing Device Context Preparation</A> <LI><A HREF="#Heading13">Aborting the Print Job</A> </UL> <LI><A HREF="#Heading14">Direct Printing Without the Framework</A> <UL> <LI><A HREF="#Heading15">Invoking the Print Dialog Box Directly</A> <LI><A HREF="#Heading16">Using StartDoc() and EndDoc()</A> <LI><A HREF="#Heading17">Using StartPage() and EndPage()</A> </UL></UL><P><HR SIZE="4"><BR><I>by Jon Bates</I></P><P><I></I><H2><A NAME="Heading1"></A>Using the Framework's Functionality</H2><P>The SDI and MDI frameworks created by the AppWizard add the hooks for printingand previewing by default. These can be turned off by unchecking the Printing andPrint Preview option in Step 4 of the MFC AppWizard, but generally they are usefulto include in any project and add very little overhead. Most of the real work ofprinting is taken care of by the device context and GDI. The framework presents youwith a device context for a print document page; you can treat it pretty much asif it's a normal window device context.</P><P><H3><A NAME="Heading2"></A>Using Default Print Functionality</H3><P>The SDI (Single Document Interface) framework supports printing images from viewsbased on information held in the document. Because this information is already displayedin your applications views, you can probably print it by modifying the view to addprinting support.</P><P>The framework calls your OnDraw() function in the view to display an image. Thereis a corresponding OnPrint() function that it calls to let your view handle printingthe information. Often this task is simply a case of using the same drawing codeas you've implemented in your OnDraw() function. If this is so, you don't actuallyneed to implement the OnPrint() function; the framework does this by default in theCView base class and calls OnDraw(). The printer is then treated just like it wouldbe for a screen because it offers a device context for the drawing functions to use,as a substitute for the usual screen device context. Your OnDraw() function can determinewhether the device context it is passed is a screen or printer device context, butbecause the drawing functions will work in the same way on both, even this knowledgeisn't necessary.</P><P>You can explore the printing functionality added by the standard framework bycreating a standard SDI application with the AppWizard. Leave the Printing and PrintPreview option in Step 4 checked (this means you can click Finish<B> </B>on Step1) and name the project PrintIt.</P><BLOCKQUOTE> <P><HR><B>STANDARD PRINT FRAMEWORK SUPPORT</B><BR> </P> <P>The standard print and print preview support is available only in SDI and MDI applications. Dialog box-based applications must implement their own printing support.<HR></BLOCKQUOTE><P>The first thing you'll need is a graphic to print. You can create a graphicaltest display in the OnDraw() function of my CPrintItView class (just a normal CView)as shown in Listing C.1. This test displays a line-art style picture with some centralizedtext in a large font (see Figure C.1). The test image isn't too important, but itwill make a useful comparison between printed output and screen display.</P><P><H4>LISTING C.1. LST23_1.CPP--DRAWING IN OnDraw TO PRODUCE A PRINT SAMPLE.</H4><PRE>1: void CPrintItView::OnDraw(CDC* pDC)2: {3: CPrintItDoc* pDoc = GetDocument();4: ASSERT_VALID(pDoc);5:6: // TODO: add draw code for native data here7:8: // ** Set metric mapping9: pDC->SetMapMode(MM_LOMETRIC);10:11: // ** Declare and create a font 2.2cm high12: CFont fnBig;13: fnBig.CreateFont(220,0,0,0,FW_HEAVY,FALSE,FALSE,0,14: ANSI_CHARSET,OUT_DEFAULT_PRECIS,15: CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,16: FF_SWISS+VARIABLE_PITCH,"Arial");17:18: //** Select the new font and store the original19: CFont* pOldFont = pDC->SelectObject(&fnBig);20:21: //** Declare a client rectangle22: CRect rcClient;23: GetClientRect(&rcClient);24:25: // ** Convert to logical units26: pDC->DPtoLP(&rcClient);27:28: // ** Set up some drawing variables29: const int nPoints = 50;30: int xm = rcClient.Width();31: int ym = rcClient.Height();32: double dAspW = xm/(double)nPoints;33: double dAspH = ym/(double)nPoints;34:35: // ** Select a black pen36: CPen* pOldPen = 37: (CPen*)pDC->SelectStockObject(BLACK_PEN);38:39: // ** Draw the lines40: for(int i=0;i<nPoints;i++)41: {42: int xo = (int)(i * dAspW);43: int yo = (int)(i * dAspH);44:45: pDC->MoveTo(xo,0);46: pDC->LineTo(xm,yo);47: pDC->LineTo(xm-xo,ym);48: pDC->LineTo(0,ym-yo);49: pDC->LineTo(xo,0);50: }51:52: // ** Reselect the old pen53: pDC->SelectObject(pOldPen);54:55: // ** Draw the text on top56: pDC->SetTextAlign(TA_CENTER+TA_BASELINE);57: pDC->SetBkMode(TRANSPARENT);58:</PRE><PRE>59: // ** Set gray text</PRE><PRE>60: pDC->SetTextColor(RGB(64,64,64));61: pDC->TextOut(xm/2,ym/2,"Sample Print");62:63: // ** Reselect the old font64: pDC->SelectObject(pOldFont);65: }</PRE><P><A HREF="javascript:popUp('23fig01.gif')"><B>FIGURE C.1.</B></A><B> </B><I>Graphicaltest output of PrintIt in a window.a</I></P><P>Although there is a fair bit of code in this OnDraw() function, none of it isunusual. It just draws lines inside the client rectangle and writes some text inthe middle. Notice at line 9, the mapping mode is set to MM_LOMETRIC; this sets thelogical coordinates to tenths of a millimeter.</P><P>A 2.2cm high font is created at line 13 and used to draw the sample text at line61. Lines 40 to 50 draw the arty "peg and string" frame using the clientrectangle coordinates. I'll let you decipher the details; the important thing hereis to investigate the business of printing.</P><P>If you build and run the program after adding these lines to the OnDraw() functionof Listing C.1, you should see a graphical display in your application window, asshown in Figure C.1.</P><P>So the big question is this: What must you do to print this image output? Surprisinglylittle--because the standard framework tries to print this by calling your OnDraw()function and passing the device context for the printer rather than for the window.</P><P>If you click the File<B> </B>menu of the PrintIt application and choose PrintPreview, you'll see a small representation of the image in the top-left corner, althoughthe font is too big for the line drawing. This isn't the framework's fault; it hasdone its best to represent your window, but it was passed the wrong coordinates forthe device context. The problem lies with the GetClientRect()used in line 23.</P><P>Notice that GetClientRect() is a member of the view, not of the device context.This works fine for the window because the device context is the same size as thewindow rectangle. Now you're passing the window rectangle to the printer device context(which is small in comparison) but creating a 2.2cm high font that is always thesame size (because of the mapping mode).</P><P><H3><A NAME="Heading4"></A>Overriding OnPrint()</H3><P>To fix the client rectangle coordinate size problem, you must pass the correctrectangle for the printer rather than the window. Fortunately, the framework callsa virtual function that you can override in your view and use to find all the informationyou need. As you read earlier, this function is named OnPrint() and is analogousto OnDraw(). When drawing in a window, OnDraw() is called; when drawing on a printer,OnPrint() is called. You might be wondering how the drawing code in OnDraw() wasexecuted to print preview the sample graphical display. The default CView implementationof OnPrint() simply calls OnDraw(), passing its printer device context.</P><P>Your OnPrint() doesn't have to call OnDraw(); you can override OnPrint() to makeit draw something entirely different, but many applications must print out what theuser sees. These applications reuse their OnDraw() code with the printer device context.</P><P>To override the OnPrint() virtual function, perform the following steps:</P><P><DL> <DT></DT> <DD><B>1. </B>Click the ClassView tab of the Project Workspace view. <P> <DT></DT> <DD><B>2. </B>Click the top plus sign to open the view of the project classes. <P> <DT></DT> <DD><B>3. </B>Right-click the view class to which you want to add the OnPrint() override (such as CPrintItView in the PrintIt example) to display the context menu. <P> <DT></DT> <DD><B>4. </B>Select the Add Virtual Function option to display the New Virtual Override dialog box. <P> <DT></DT> <DD><B>5. </B>You should see an OnPrint virtual function in the New Virtual Functions list. <P> <DT></DT> <DD><B>6. </B>Click the Add and Edit button to start editing the OnPrint() virtual function. <P></DL><P>The standard override for OnPrint() looks like this:</P><P><PRE>void CPrintItView::OnPrint(CDC* pDC, CPrintInfo* pInfo){ // TODO: Add your specialized code here CView::OnPrint(pDC, pInfo);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -