按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
看看另一个函数OnPaint:
// in VIEWCORE。CPP
void CView::OnPaint()
{
// standard paint routine
CPaintDC dc(this);
OnPrepareDC(&dc);
OnDraw(&dc);
}
你会发现原来它们是这么分工的:
WM_MAND
CView::OnPrint 唯「打印」才有之工作,将在此进行
(ID_FILE_PRI NT) CView::OnPrint
CView::OnDraw 「打印」与「显示」共通的
CView::OnDraw
工作,在此进行
WM_ PA INT CView ::OnPaint 唯「显示」才有的工作,将在此进行
CView::OnPaint
所谓「显示」是指输出到屏幕上,「打印」是指输出到打印机上。
由同一函数完成显示(display )与打印(print )动作,才能够达到「所见即所得」(What
You See Is What You Get ,WYSIWYG )的目的。如果你不需要一个WYSIWYG 程序,
可以改写OnPrint 使它不要调用OnDraw,而调用另一个绘图例程。
不要认为什么情况下都需要WYSIWYG 。一个文字编辑器可能使用粗体字打印但使用控
制码在屏幕上代表这粗体字。
684
…………………………………………………………Page 747……………………………………………………………
第 12 章 列印與預樱А�
Scribble 打印机制的增强
MFC 预设的打印机制够聪敏了,但还没有聪敏到解决所有的问题。这些问题包括:
■打印出来的影像可能不是你要的大小
■不会分页
■没有表头(header )
■没有页尾(footer )
毕竟屏幕输出和打印机输出到底还是有着重大的差异。窗口有卷动杆而打印机没有,这
伴随而来的就是必须计算Document 的大小和纸张的大小,以解决分页的问题;此外,
我们必须想想,在MFC 预设的打印机制中,改写哪一个地方,才能让我们有办法在
Document 的输出页加上表头或页尾。
打印机的页和文件的页
首先,我们必须区分「页」对于Document 和对于打印机的不同意义。从打印机观点来
看,一页就是一张纸,然而一张纸并不一定容纳Document 的一页。例如你想印一些通
讯资料,这些资料可能是要被折叠起来的,因此一张纸印的是Document 的第一页和最
后一页(亲爱的朋友,想想你每天看的报纸)。又例如印一个巨大的电子表格,它可能是
Document 上的一页,却占据两张A4 纸。
MFC 这个Application Framework 把关于打印的大部份信息都记录在CPrintInfo 中,其
中数笔资料与分页有密切关系。下表是取得分页资料的相关成员,其中只有SetMaxPage
和m_nCurPage 和m_nNumPreviewPages 在Scribble 程序中会用到,原因是Scribble
程序对许多问题做了简化。
685
…………………………………………………………Page 748……………………………………………………………
第篇 深入 MFC 程式設計
CPrintInfo 成员名称 参考到的打印页
GetMinPage/SetMinPage Document 中的第一页
GetMaxPage/SetMaxPage Document 中的最后一页
GetFromPage 将被印出的第一页(出现在【打印】对话框,图12…1b)
GetToPage 将被印出的最后一页(出现在【打印】对话框)
m_nCurPage 目前正被印出的一页(出现在【打印状态】对话框)
m_nNumPreviewPages 预览窗口中的页数(稍后将讨论之)
注:页码从1 (而不是0 )开始。
CPrintInfo 结构中记录的「页」数,指的是打印机的页数;Framework 针对每一「页」
调用OnPrepareDC 以及OnPrint 时,所指的「页」也是打印机的页。当你改写
OnPreparePrinting 时指定Document 的长度,所用的单位也是打印机的「页」。如果
Document 的一页恰等于打印机的一页(一张纸),事情就单纯了;如果不是,你必须在
两者之间做转换。
Scribble Step5 设定让每一份Document 使用打印机的两页。第一页只是单纯印出文件名
称(文件名称),第二页才是文件内容。假设我利用View 窗口卷动杆在整个Document
四周画一四方圈的话,我希望这一四方圈落入第二页(第二张纸)中。当然,边界留白
必须考虑在内,如图12…6。除此之外,我希望第二页(文件内容)最顶端留一点空间,
做为表头。本例在表头中放的是文件名称。
686
…………………………………………………………Page 749……………………………………………………………
第 12 章 列印與預樱А�
图12…6 Scribble Step5 的每一份文件打印时有两页,第一页是文件名称,
第二页是文件内容, 最顶端留有一个表头。
配置GDI 绘图工具
绘图难免需要各式各样的笔、刷、颜色、字形、工具。这些GDI 资源都会占用内存,
而且是GDI 模块的heap 。虽说Windows 95 对于USER 模块和GDI 模块的heap 已
有大幅改善,使用32 位heap ,不再局限64KB,但我们当然仍然不希望看到浪费的情
况发生,因此最好的方式就是在打印之前配置这些GDI 绘图对象,并在打印后立刻释放。
看看图12…5,配置GDI 对象的最理想时机显然是OnBeginPrinting,两个理由:
1。 每当Framework 开始一份新的打印工作,它就会调用此函数一次,因此不同
打印工作所需的不同工具可在此有个替换。
2。 此函数的参数是一个和「打印机DC 」有附着关系的CDC 对象指针,我们直接
从此一CDC 对象中配置绘图工具即可。
687
…………………………………………………………Page 750……………………………………………………………
第篇 深入 MFC 程式設計
配置得来的GDI 对象可以储存在View 的成员变量中,供整个打印过程使用。使用时
机当然是OnPrint。如果你必须对不同的打印页使用不同的GDI 对象,CPrintInfo 中的
m_nCurPage 可以帮你做出正确的决定。
释