按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
CSize(10; 10); // TODO: adjust the minimum pane size
656
…………………………………………………………Page 719……………………………………………………………
第 11 章 View 功能之加強與重繪效率之提昇
pContext);
}
本章回顾
这一章里我们追求的是精致化。
Scribble Step3 已经有绘图、文件读写、变化笔宽的基本功能,但是「连接到同一份
Document 的不同的Views 」之间却不能够做到同步更新的视觉效果,此外View 窗口
中没有滚动条也是遗憾的事情。
Scribble Step4 弥补了上述遗憾。它让「连接到同一份Document 的不同的Views 」之间
做到同步更新…关键在于CDocument::UpdateAllViews 和CView::Update 两个虚拟函
式。而由于同步更新引发的绘图效率问题,所以我们又学会了如何设计所谓的hint ,让
绘图动作更聪敏些。也因为hint 缘故,我们改变了Document 的格式,为每一线条加上
一个外围四方形记录。
在滚动条方面,MFC 提供了一个名为CScrollView 的类别,内有滚动条功能,因此直接拿来
用就好了。我们唯一要担心的是,从CView 改为CScrollView,原先的OnDraw 绘图动
作要不要修改?毕竟,卷来卷去把原点都不知卷到哪里去了,何况还有映射模式(坐标
系统)的问题。这一点是甭担心了,因为application framework 在调用OnDraw 之前,
已经先调用了OnPrepareDC,把问题解决掉了。唯一要注意的是,送进OnDraw 的滑
鼠坐标点应该改为逻辑坐标,以文件左上角为原点。DP2LP 函数可以帮我们这个忙。
此外,我们接触了另一种新而且更精致的UI 接口:分裂窗口,让一个窗口分裂为数个
窗口,每一个窗口容纳一个View 。MFC 提供CSplitterWnd 做此服务。
657
…………………………………………………………Page 720……………………………………………………………
第篇 深入 MFC 程式設計
658
…………………………………………………………Page 721……………………………………………………………
第 12 章 列印與預樱А
12
第 章
打印与预览
「打印」绝对是个大工程,「打印预览」是个更大的工程。如果你是一位SDK 程序员,
而你分配到的工作是为公司的绘图软件写一个印前预浏系统,那么我真的替你感到忧
郁。可如果你使用MFC ,情况又大不相同了。
概观
Windows 的DC 观念,在程序的绘图动作与实际设备的驱动程序之间做了一道隔离,使
得绘图动作完全不需修改就可以输出到不同的设备上:
Display DC Display DRV Display
Display DC Display DRV Display
GDI calls
Printer DC Printer DRV Printer
Printer DRV Printer
即便如此,打印仍然有其琐碎的工作需要由程序员承担。举个例子,屏幕窗口有卷动杆,
打印机没有,于是「分页」就成了一门学问。另外,如何中断打印?如何设计水平方向
659
…………………………………………………………Page 722……………………………………………………………
第篇 深入 MFC 程式設計
(landscape)或垂直方向(portrait )的打印输出?
landscape,风景画,代表横向打印;portrait ,人物画,代表纵向打印。
如果曾经有过SDK 程序经验,你一定知道,把资料输出到屏幕上和输出到打印机上几
乎是相同的一件事,只要换个DC (注)就好了。MFC 甚至不要求程序员的任何动作,
即自动供应打印功能和预览功能。拿前面各版本的Scribble 为例,我们可曾为了输出任
何东西到打印机上而特别考虑什么程序代码?完全没有!但它的确已拥有打印和预览功
能,你不妨执行Step4 的【File/Print。。。 】以及【File/Print Preview 】看看,结果如图12
1a。
注:DC 就是Device Context ,在Windows 中凡绘图动作之前一定要先获得一个DC ,它
可能代表全屏幕,也可能代表一个窗口,或一块内存,或打印机。。。。DC 中有许多绘图
所需的元素,包括坐标系统(映射模式)、原点、绘图工具(笔、刷、颜色。。。)等等。
它还连接到低阶的输出装置驱动程序。由于DC ,我们在程序中对屏幕作画和对打印机
作画的动作才有可能完全相同。
Scribble 程序之所以不费吹灰之力即拥有打印与预览功能,是因为负责资料显示的
CSribbleView::OnDraw 函数接受了一个DC 参数,此DC 如果是display DC ,所有的
输出就往屏幕送,如果是printer DC ,所有输出就往打印机送。至于OnDraw 到底收到
什么样的DC ,则由Framework 决定…想当然耳Framework 会依使用者的动作决定之。
MFC 把整个打印机制和预览机制都埋在application framework 之中了,我们因此也有了
标准的UI 接口可以使用,如标准的【打印】对话框、【打印设定】对话框、【打印中】
对话框等等,请看图12…1。
我将在这一章介绍MFC 的打印与预览机制,以及如何强化它。
660
…………………………………………………………Page 723……………………………………………………………
第 12 章 列印與預樱А
图12…1a 不需考虑任何与打印相关的程序动作, Scribble 即已具备打印与预
览功能 ( 只要我们一开始在AppWizard 的步骤四对话框中选择
【Printing and Print Preview】项 目)。打印出来的图形大小
并不 符合理想, 从预览画面中就可察知。这正是本章要改善的地方。
图12…1b 标准的打印UI 接口。本图是选按Scribble 的 【File/Print。。。】命
令项之后获得的 【打印】对话框。
661
…………………………………………………………Page 724……………………………………………………………
第篇 深入 MFC 程式設計
图12…1c 你可以选按Scribble 的 【File/Print Setup。。。 】命令项, 获得设
定打印机的机会。
图12…1d 打印过程中会出现一个标准的 【打印状态】对话框,允许使用者中
断打印动作。
Scribble Step5 加强了打印功能以及预览功能。MFC 各现成类别之中已有打印和预览机
制,我要解释的是它的运作模式、执行效果、以及改善之道。图12…2 就是Scribble Step5
的预览效果,UI 方面并没有什么新东西,主要的改善是,图形的输出大小比较能够被接
受了,每一份文件并且分为两页,第一页是文件名称(文件名称),第二页才是真正的
文件内容,上有一表头。
662
…………………………………………………………Page 725……………………………………………………………
第 12 章 列印與預樱А
图12…2 Scribble Step5 打印预览。第一页是文件名称,第二页是文件内容。
打印动作的背景原理
开始介绍MFC 的打印机制之前,我想,如果先让你了解打印的背后原理,可以帮助你
掌握其本质。
Windows 的所有绘图指令,都集中在GDI 模块之中,称为GDI 绘图函数,例如:
TextOut(hPr; 50; 50; szText; strlen(szText)); // 输出一字符串
Rectangle(hPr; 10; 10; 50; 40); // 画一个四方形
Ellipse(hPr; 200; 50; 250; 80); // 画一个椭圆形
Pie(hPr; 350; 50; 400; 100; 400; 50; 400; 100); // 画一个圆饼图
MoveTo(hPr; 50; 100); // 将画笔移动到新位置
LineTo(hPr; 400; 50); // 从前一位置画直线到新位置
图形输往何方?关键在于DC ,这是任何GDI 绘图函数的第一个参数,可以是GetDC
或BeginPaint 函数所获得的「显示屏DC 」(以下是SDK 程序写法):
663
…………………………………………………………Page 726……………………………………………………………
第篇 深入 MFC 程式設計
HDC hDC;
PAINTSTRUCT ps; // paint structure
hDC = BeginPaint(hWnd; &ps);
也可以是利用CreateDC 获得的一个「打印机DC 」:
HDC hPr;
hPr = CreateDC(lpPrintDriver; lpPrintType; lpPrintPort; (LPSTR) NULL);
其中前三个参数分别是与打