1. CView的各种派生类:
1) MFC为了方便,还从CView派生出一些具有特殊功能的视图供程序员使用;
2) 其中最常用的有CScrollView、CListView、CTreeView、CHtmlView这四个,分别用来建立可滚动的视图、基于列表的视图、属性视图(资源管理器就是典型的一种)和浏览器视图(浏览器软件常用的一种视图);
3) 这里我们介绍CScrollView滚动视图;
2. CScrollView简介:
1) CScrollView为CView添加了基本的滚动功能;
2) 它可以自动处理跟滚动相关的事物而无需程序员维护,但是用户也可以调用一些成员函数来指定滚条的位置、检索滚条当前位置等;
3) 在没有使用CScrollView时,重画客户区需要让视图的内容伴随着滚条的位置而变化,这使得重画非常不方便,而现在这些琐碎的事物都可以由CScrollView来自动完成,OnDraw函数的覆盖就跟普通的CView覆盖OnDraw一模一样,无需加入复杂的和滚条同步的逻辑,除非希望优化滚条操作才会用到一些特殊的和滚条有关的逻辑;
3. 视图的创建和初始化:
1) 创建滚动视图的基本步骤:
i. 使用Wizzard创建MFC应用程序的最后一步(第6步)中选中视图类,并且选中其继承的基类为CScrollView即可;
ii. 覆盖视图类的OnInitUpdate函数,在该函数中使用SetScrollSizes来指定视图的尺寸,如果使用Wizzard来创建则会自动给出默认的OnInitUpdate的实现,里面也会自动调用SetScrollSizes,并将视图的宽和高默认设置为100像素;
iii. 将视图当做普通视图来实现OnDraw函数即可;
2) 术语——逻辑视图和物理视图:
i. 物理视图:是指实际占据屏幕的视图窗口和空间;
ii. 逻辑视图:可以使用滚条看到的完整的虚拟视图窗口和空间,一般逻辑视图≥物理视图;
!!当物理视图尺寸大于逻辑视图尺寸时滚条就会自动隐藏,并且滚条可以自动根据物理和逻辑视图的相对比例来调整自身大小,这些细节都不需要用户关心,全部都自动实现;
3) SetScrollSizes:
i. 在OnInitUpdate中调用,用来初始化视图的逻辑尺寸、页尺寸和行尺寸;
!页尺寸:单击滚轴时将滚动一页的大小;
!行尺寸:单击滚动箭头时将滚动一行的大小;
!!这两个尺寸可以用户自由设定,但一般情况下页尺寸要远大于行尺寸,不能瞎定义;
ii. 原型:
void CScrollView::SetScrollSizes(
int nMapMode, // 映射模式,后面的尺寸将基于该映射模式
SIZE sizeTotal, // 逻辑视图的宽和高
const SIZE& sizePage = sizeDefault, // 页尺寸
const SIZE& sizeLine = sizeDefault // 行尺寸
);
!!对于sizePage和sizeLine,第一个分量为水平滚条的变化单位,第二个分量表示垂直方向的变化单位;
!!nMapMode不能指定MM_ISOTROPIC和MM_ANISOTROPIC!!即两个自定义的映射模式不能指定,其余的都能指定;
iii. SetScrollSizes非常智能的一点:就是在该函数中指定了映射模式之后就不需要再在OnDraw函数中再指定一遍映射模式了,OnDraw函数中已经自动默认使用SetScrollSizes中设定的映射模式了,这为用户减轻了不少负担!!
4. 在OnDraw以外绘制输出的若干注意事项:
1) 在OnDraw以外绘制输出如果还是按照普通视图的方式执行则滚动的功能无法展现,就还是跟普通视图没两样,即输出时不会考虑映射模式和滚动的位置;
2) 在OnDraw以外绘制输出必须先使用CScrollView的OnPrepareDC做好滚动输出的准备,准备完成之后再按照普通视图那样进行输出,这样就会自动展现出滚动效果了:
i. 原型:
virtual void CView::OnPrepareDC(
CDC* pDC,
CPrintInfo* pInfo = NULL // 打印信息,暂不用管
);
!!MFC在CScrollView继承CView过程中覆盖了该函数,在该函数调用了SetMapMode和SetViewportOrg将映射模式设置成SetScrollSizes中指定的映射模式,并可以将传进去的设备描述表赋予ScrollView滚动的特性;
ii. 我们可以看一下CScrollView的OnPaint的源码:
...
CPaintDC dc(this);