第11章View功能之加強与
重绘效率之提升
1. 基本上要使View 窗口具备滚动条,你必须做到下列事情:
A.定义Document 大小。如果没有大小,Framework就没有办法计算滚动条尺寸,
以及卷动比例。这个大小可以是常数,也可以是个储存在每一Document 中的
变量,随着执行时期变动。
B. 以CScrollView 取代CView
C. 只要Document 的大小改变,就将尺寸传给CScrollView的SetScrollSizes 函
式。如果程序设定Document 为固定大小(本例就是如此),那么当然只要一
开始做一次滚动条设定动作即可。
D. 注意装置坐标(窗口坐标)与逻辑坐标(Document 坐标)的转换。
2. 以下分四个步骤修改Scribble源代码:
A.Document 的大小。我们的作法是设定一个变量,代表大小,并在Document 初
始化时设定其值,此后全程不再改变(以简化问题)。这个成员变量在文件进行文件读写(Serialization)时也应该并入文件内容中。
B.将CScribbleView 的父类别由CView 改变为CScrollView。同时准备改写其虚拟函数
OnInitialUpdate,为的是稍后我们要在其中,根据Document 的大小,设定卷动范围
C. 改写OnInitialUpdate,在其中设定滚动条范围。这个函数的被调用时机是在View 第
一次附着到Document 但尚未显现时,由Framework 调用之。
SetScrollSizes 总共有四个参数:
int nMapMode:代表映射模式(Mapping Mode)
SIZE sizeTotal:代表文件大小
const SIZE& sizePage:代表一页大小(预设是文件大小的1/10)
const SIZE& sizeLine:代表一行大小(预设是文件大小的1/100)
D. 修正鼠标坐标。虽说OnDraw 不必因为坐标原点的变化而有任何改变,但是幕后出
力的CScrollView::OnPrepareDC却不知道什么是Windows 消息.
Windows坐标系分为逻辑坐标系和设备坐标系两种,GDI支持这两种坐标系。一般而言,GDI的文本和图形输出函数使用逻辑坐标,而在客户区移动或按下鼠标的鼠标位置是采用设备坐标。
<1>逻辑坐标系是面向DC的坐标系,这种坐标不考虑具体的设备类型,在绘图时,Windows会根据当前设置的映射模式将逻辑坐标转换为设备坐标。
<2>设备坐标系是面向物理设备的坐标系,这种坐标以像素或设备所能表示的最小长度单位为单位,X轴方向向右,Y轴方向向下。设备坐标系的原点位置(0, 0)不限定在设备显示区域的左上角。
设备坐标系分为屏幕坐标系、窗口坐标系和客户区坐标系三种相互独立的坐标系。
屏幕坐标系以屏幕左上角为原点,一些与整个屏幕有关的函数均采用屏幕坐标,如GetCursorPos()、SetCursorPos()、CreateWindow()、MoveWindow()。弹出式菜单使用的也是屏幕坐标。窗口坐标系以窗口左上角为坐标原点,它包括窗口标题栏、菜单栏和工具栏等范围。客户区坐标系以窗口客户区左上角为原点,主要用于客户区的绘图输出和窗口消息的处理。鼠标消息的坐标参数使用客户区坐标,CDC类绘图成员函数使用与客户区坐标对应的逻辑坐标。2)坐标之间的相互转换编程时,有时需要根据当前的具体情况进行三种设备坐标之间或与逻辑坐标的相互转换。MFC提供了两个函数CDC::DPtoLP()和CDC:: LPtoDP()用于设备坐标与逻辑坐标之间的相互转换。MFC提供了两个函数CWnd::ScreenToClient()和CWnd::ClientToScreen()用于屏幕坐标与客户区坐标的相互转换。
3. 分裂窗口的程序概念
A.须有三个窗口通力合作完成显示任务
1. Document Frame 窗口:负责一般性窗口行为。其类别衍生自CMDIChildWnd。
2. Splitter 窗口:负责管理各窗口。通常直接使用CSplitterWnd类别。
3 .View 窗口:负责资料的显示。其类别衍生自CView。
4.CSplitterWnd::Create 正是产生分裂窗口的关键,它有七个参数:
1. 表示父窗口。这里的this代表的是CChildFrame窗口。
2. 分裂窗口的水平窗口数(row)
3. 分裂窗口的垂直窗口数(column)
4. 窗口的最小尺寸(应该是一个CSize对象)
5. 在窗口上使用哪一个View类别。此参数直接取用Framework交给
OnCreateClient 的第二个参数即可。
6. 指定分裂窗口的风格。默认值是:WS_CHILD|WS_VISIBLE|WS_HSCROLL|
WS_VSCROLL|SPLS_DYNAMIC_SPLIT,意思就是一个可见的子窗口,有着水平卷
轴和垂直滚动条,并支持动态分裂。关于动态分裂(以及所谓的静态分裂),
7. 分裂窗口的ID。默认值是AFX_IDW_PANE_FIRST,这将成为第一个窗口的ID。
默认ID:ID_WINDOW_SPLIT
在Resource View资源视图中,打开Menu下的IDR_MAINFRAME菜单,在View下添加一个菜单项,Caption设为Splitter Window,ID设为(一定要设为)ID_WINDOW_SPLIT。这样在运行结果界面中点击此菜单项时MFC会执行一些操作显示动态分割窗口。
运行实例:
第12章打印预览
本章只是一些关于打印与预览的知识点,基本上依靠vs2008工具建起来的文档都有打印和预览的功能。
1. 程序流程
2. 在MFC 应用程序中,View 和applicationframework 分工合力完成打印工作
Application framework 的责任是:
显示【Print】对话框
为打印机产生一个CDC 对象。
调用CDC 对象的StartDoc 和EndDoc 两函数。
持续不断地调用CDC 对象的StartPage,通知View 应该输出哪一页;一页打印
完毕则调用CDC 对象的EndPage。
我们(程序员)在View 对象上的责任是:
通知application framework 总共有多少页要打印。
application framework 要求打印某特定页时,我们必须将Document中对应的部
份输出到打印机上。
配置或释放任何GDI 资源,包括笔、刷、字形...等等。
如果需要,送出任何escape 码改变打印机状态,例如走纸、改变打印方向等等。
程序运行视例: