CView的派生类: CScrollView
调用SetScrollSizes() 让 CScrollView 知道你的“逻辑视图”的大小,获得大小信息后,操纵传递给
OnDraw() 的DC,从而支持滚动
CScrollView
如何运作:
CScrollView ( VIEWSCRL.CPP )
· m_nMapMode —— 在 SetScrollSizes()
中,可以为应用程序指定一个映射模式。默认为MM_NONE,CScrollView定义为(MM_SCALETOFIT)。
· m_totalLog —— 逻辑坐标中视图的大小,这个值通过 SetScrollSizes() 成员函数传递给
CScrollView。
· m_totalDev —— 设备坐标中视图的大小。
· m_pageDev —— 设备坐标中一个页的大小。
· m_lineDev —— 设备中一条线的大小。
· m_bCenter —— CPreviewView 使用这个数据成员进入窗口中的视图。
· CenterOnPoint() —— 将视图集中于一点,由 CPreviewView 调用
· ScrollToDevicePosition() —— 负责滚动视图。通过调用::SetScrollPos() 和
::CSrollWindow() 更新滚动条,来完成视图的滚动条。
· UpdateBars() —— CScrollView 在初始化的时候和窗口大小发生变化的时候调用。责任是根据
GetScrollBarState() 的返回信息隐藏、显示、初始化滚动条。
· GetTrueClientSize() —— 用来确定用户视图是否足够大(是否需要滚动条),只有 UpdateBars
才会调用这个函数。
· GetScrollBarSizes() ——
确定滚动条的宽度和高度,考虑了窗口的风格和边框的宽度。
· GetScrollBarState() —— 获取 CScrollView
所需要的关于视图的状态。
· CalcWindowRect() —— 计算窗口矩形的大小,考虑滚动条和其他窗口饰物的大小。
· OnPrepareDC() —— CScrollView 和 ONVScroll()
交互的关键。
· OnScroll() —— OnHScroll() 和
OnVScroll两个消息处理函数都调用了这个函数。根据页面大小和行大小确定要滚动的量。再调用
OnScrollBy()
· OnScrollBy() —— 检查需要滚动的量是否超出了滚动条的范围和视图的逻辑大小。若没有,调用
::SetScrollPos() 移动滚动条,在调用 ::ScrollWindow().
· OnSize() —— 若 CScrollView 不是处于“scale-to-fit”模式下,OnSize() 调用
UpdateBars();否则,调用 SetScaleToFitSize()。
· OnHScroll() —— 调用 OnScroll() 的消息处理函数。
· OnVScroll() —— 调用 OnScroll() 的消息处理函数。
CScrollView::SetScrollSizes()
(VIEWSCRL.cpp)
《深入解析MFC》P239
①. 将 m_nMapMode 初始化为提供的新映射模式, m_totalLog
的初始化值是sizeTotal 参数。
②. 在栈上创建一个 CWindowDC,并且在设置了映射模式之后,使用DC
来计算视图大小、页面大小和行大小的设备坐标。
③.
将逻辑坐标转化为设备坐标后,检查确保用户提供了一个非默认的值,若为默认值0,页面大小设为视图大小的1/10,行为页的1/10或视图的1/100。
④. 若需要,调用 UpdateBars() 和
Invalidate()。设置滚动条,若修改了映射模式,重画。
CScrollView::OnPrepareDC()
在调用 OnDraw()之前调用
①. 设置映射模式,若在“scale-to-fit”模式下,模式设置为
ANISOTROPIC,然后对窗口和视图端口操作,知道视图的大小和客户窗口匹配。
若不是,调用 SetMapMode(), 参数是用户通过 SetScrollSizes()
指定的映射模式。
②. 在栈上创建一个 CPoint ptVpOrg(assume no shift for
printing),初始化为 0,0。 若视图不在打印, ptVpOrg =
-GetDeviceScrollPosition()
③. 调用 CDC::SetViewportOrg( ptVpOrg )。然后调用
CView::OnPrepareDC()。