按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
m_rectDraw 四方形的一部份,代表表头页尾所占空间。OnPrint 也可以根据m_rectDraw
的数值决定有多少内容要放在打印页的主体上。
我们甚至可能因为表头页尾的加入,而需要修改OnDraw,因为能够放到一张打印纸上
的文件内容势必将因为表头页尾的出现而减少。不过,还好本例并不是这个样子。本例
不设页尾,而文件大小在MM_LOENGLISH 映射模式下是8 英伎眇9 英几撸旁谝挥
页A4 纸张(210 x 297 公厘)或Letter Size (8…1/2 x 11 英迹┲秸胖卸即麓掠杏唷
695
…………………………………………………………Page 758……………………………………………………………
第篇 深入 MFC 程式設計
#0001 void CScribbleView::PrintPageHeader(CDC* pDC; CPrintInfo* pInfo;
#0002 CString& strHeader)
#0003 {
#0004 // Print a page header consisting of the name of
#0005 // the document and a horizontal line
#0006 pDC…》SetTextAlign(TA_LEFT);
#0007 pDC…》TextOut(0;…25; strHeader); // 1/4 inch down
#0008
#0009 // Draw a line across the page; below the header
#0010 TEXTMETRIC textMetric;
#0011 pDC…》GetTextMetrics(&textMetric);
#0012 int y = …35 textMetric。tmHeight; // line 1/10th inch below text
#0013 pDC…》MoveTo(0; y); // from left margin
#0014 pDC…》LineTo(pInfo…》m_rectDraw。right; y); // to right margin
#0015
#0016 // Subtract out from the drawing rectange the space used by the header。
#0017 y …= 25; // space 1/4 inch below (top of) line
#0018 pInfo…》m_rectDraw。top += y;
#0019 }
动态计算页码
某些情况下View 类别在开始打印之前没办法事先知道Document 的长度。
假设你的程序并不支持「所见即所得」,那么屏幕上的Document 就不会对应到它打印
时真正的长度。这就引起了一个问题,你没有办法在改写OnPreparePrinting 时,利用
SetMaxPage 为CPrintInfo 结构设定一个最大页码,因为这时候的你根本不知道Document
的长度。而如果使用者不能够在【打印】对话框中指定「结束页码」,Framework 也就
不知道何时才停止打印的循环。唯一的方法就是边印边看,View 类别必须检查是否目前
已经印到Document 的尾端,并在确定之后通知Framework 。
那么我们的当务之急是找出在哪一个点上检查Document 结束与否,以及如何通知
Framework 停止打印。从图12…5 可知,打印的循环动作的第一个函数是OnPrepareDC,
我们可以改写此一函数,在此设一道关卡,如果检查出Document 已到尾端,就要求中
止打印。
696
…………………………………………………………Page 759……………………………………………………………
第 12 章 列印與預樱А�
Framework 是否结束打印,其实全赖CPrintInfo 的m_bContinuePrinting 字段。此字段
如果是FALSE ,Framework 就中止打印。预设情况下OnPrepareDC 把此字段设为
FALSE 。小心,这表示如果Document 长度没有指明,Framework 就假设这份Document
只有一页长。因此你在调用基础类别的OnPrepareDC 时需格外注意,可别总以为
m_bContinuePrinting 是TRUE。
打印预览( Print Preview)
什么是打印预览?简单地说,把屏幕仿真为打印机,将图形输出于其上就是了。预览的
目的是为了让使用者在打印机输出之前,先检查他即将获得的成果,检查的重要项目包
括图案的布局以及分页是否合意。
为了完成预览功能,MFC 在CDC 之下设计了一个子类别,名为CPreviewDC。所有其
他的CDC 对象都拥有两个DC ,它们通常井水不犯河水;然而CPreviewDC 就不同,
它的第一个DC 表示被仿真的打印机,第二个DC 是真正的输出目的地,也就是屏幕
(预览结果输出到屏幕,不是吗?! )
一旦你选择【File/Print Preview 】命令项,Framework 就产生一个CPreviewDC 对象。只
要你的程序曾经设定打印机DC 的特征(即使没有动手设定,也有其默认值),Framework
就会把同样的性质也设定到Preview DC 上。举个例子,你的程序选择了某种打印字形,
Framework 也会对屏幕选择一个仿真打印机输出的字形。一旦程序要做打印预览,
Framework 就透过仿真的打印机DC ,再把结果送到显示屏DC 去。
为什么我不再像前面那样去看整个预览过程中的调用堆栈并追踪其源代码呢?因为预览
对我们而言太完善了,几乎不必改写什么虚拟函数。唯一在Scribble Step5 中与打印预览
有关系的,就是下面这一行:
BOOL CScribbleView::OnPreparePrinting(CPrintInfo* pInfo)
{
pInfo…》SetMaxPage(2); // the document is two pages long:
// the first page is the title page
// the second is the drawing
697
…………………………………………………………Page 760……………………………………………………………
第篇 深入 MFC 程式設計
BOOL bRet = DoPreparePrinting(pInfo); // default preparation
pInfo…》m_nNumPreviewPages = 2; // Preview 2 pages at a time
// Set this value after calling DoPreparePrinting to override
// value read from 。INI file
return bRet;
}
现在,Scribble Step5 全部完成。
本章回顾
前面数章中早就有了打印功能,以及预览功能。我们什么也没做,只不过在AppWizard 的
第四个步骤中选了【Printing and Print Preview 】项目而已。这足可说明MFC 为我们做掉
了多少工作。想想看,一整个打印与预览系统耶。
然而我们还是要为打印付出写码代价,原因是预设的打印大小不符理想,再者当我们想
加点标题、表头、页尾时,必得亲自动手。
延续前面的风格,我还是把MFC 提供的打印系统的背后整个原理挖了出来,使你能够
清楚知道在哪里下药。在此之前,我也把Windows 的打印原理(非关MFC )整理出来,
这样你才有循序渐进的感觉。然后,我以各个小节解释我们为MFC 打印系统所做的补
强工作。
现在的Scribble,具备了绘图能力,文件读写能力,打印能力,预览能力,丰富的窗口
表现能力。除了Online Help 以及OLE 之外,所有大型软件该具备的能力都有了。我
并不打算在本书之中讨论Online Help ,如果你有兴趣,可以参考Visual C++ Tutorial (可
在Visual C++ 的Online 资料中获得)第10 章。
我也不打算在本书之中讨论OLE,那牵扯太多技术,不在本书的设定范围。
Scribble Step5 的完整源代码,列于附录B。
698
…………………………………………………………Page 761……………………………………………………………
第 12 章 列印與預樱А�
699
…………………………………………………………Page 762……………………………………………………………
第篇 深入 MFC 程式設計
700
…………………………………………………………Page 763……………………………………………………………
第 13 章 多重文件與多重顯示
13
第 章
多重文件与多重显示
你可能会以【Window/New Window 】为同一份文件制造出另一个View 窗口,也可能设
计分裂窗口,以多个窗口呈现文件的不同角落(如第11 章所为)。但,这两种情况都
是以相同的显示方式表达文件的内容。
如何突破一成不变的显示方法,达到丰富的表现效果?
这一章我将对于Document/View 再作各种深入应用。重要放在显象技术以及多重文件的
技术上。
MDI 和 SDI
首先再让我把MDI 和SDI 的观念厘清楚。
在传统的SDK 程序设计中,所谓MDI 是指「一个大外框窗口,内部可容纳许多小子
窗口」的这种程序风格。内部的小子窗口即是「Document 窗口」…虽然当时并未有如
MFC 所谓的Document 观念。此外,「MDI 风格