现在的位置: 首页 > 综合 > 正文

孙鑫VC学习笔记:第十一讲 (五) 如何使窗口具有滚动条

2013年01月28日 ⁄ 综合 ⁄ 共 1746字 ⁄ 字号 评论关闭

如何使窗口具有滚动条?

本程序的CGraphicView 类是从View类继承的
 class CGraphicView : public Cview
首先将基类改成CScrollView
 class CGraphicView : public CScrollView
然后将源文件cpp文件中的CView全部替换成CScrollView
在文件中替换字或词的步骤,
 从菜单中选择 Edit->Replace,
 在弹出的对话框中再选择 Match whole word only(仅全词匹配)
--------------------------------------------------------------------------------
要使窗口可以滚动,还需要设置一些滚动的参数:
用SetScrollSizes方法来设置映射模式、滚动视图总的尺寸等等
而这个函数最好在虚函数的重载函数OnInitiaUpdate里面调用。
这个虚函数在一个视图与一个文档关联之后调用,也就是在窗口完全创建之后第一个调用的函数。
不过它的调用是在OnDraw函数调用之前。所以这个函数可以做一些窗口创建之后的初始化工作。

 void CGraphyicView::OnInitialUpdate()
 {
  CScrollView::OnInitialUpdate();
  SetScrollSizes(MM_TEXT,CSize(800,600));
 }

--------------------------------------------------------------------------------

程序运行之后,将窗口的大小调到小到800*600时,就可以看到滚动条了。
但是我们发现一个问题,先将垂直滚动条下拉一些,然后在窗口右下角画一条直线,将其最小化,还原之后直线的位置上移了,这是什么原因呢?

调试之后,可以断定OnLButtonDown与重绘函数OnDraw中所画图形的三个要素相同,所以不是它们的问题。

在前面研究窗口重绘为什么调用OnDraw函数的时候,
void CView::OnPaint()
 {
 // standard paint routine
  CPaintDC dc(this);
  OnPrepareDC(&dc);
  OnDraw(&dc);
 }
发现在调用OnDraw之前调用了OnPrepareDC ,问题就出在这里。 
在MFC资源文件中去查看OnPrepareDC 发现这样一条代码:pDC->SetViewportOrg(ptVpOrg);
调试一下,发现ptVpOrg=(x=0, y= -150);  可见OnPrepareDC调整了显示上下文的属性将视口的原点设置为(0,-150),根据公式yViewPort=yWindow-yWinOrg+yViewOrg;得到设备点y坐标出现在原先显示地方的上方。
--------------------------------------------------------------------------------
关于解决办法的说明:
首先,绘制图形之后保存坐标点之前调用OnPrepareDC调整显示上下文的属性,将视口原点设置为(0,-150)然后调用设备坐标转换逻辑坐标函数DPtoLP将设备坐标(680,390)转换为逻辑坐标,
 根据公式  yWindow=yViewport-yViewOrg+yWinOrg;得到y坐标为540。
窗口重绘时会先调用OnPrepareDC,调整显示上下文的属性,将视口的原点设置为(0,-150)
然后GDI函数用逻辑坐标点(680,540)绘制图形,被转换为(680,390)

所以解决的办法就是在OnLButtonDown函数中,绘制完图形之后,保存图形元素之前 加入下面代码:
 OnPrepareDC(&dc);
 dc.DPtoLP(&m_ptOrigin); //视口(设备)坐标和窗口(逻辑)坐标
 dc.DPtoLP(&point);

当滚动条在最上端,窗口发生重绘时OnPrepareDC调整显示上下文,
会将视口的原点设置为(0,0),而不是(0,-150)
OnPrepareDC会随时根据滚动窗口的位置来调整视口的原点 

抱歉!评论已关闭.