OnPaint和OnDraw
为什么发生重绘消息的时候,OnDraw会响应?
因为OnPaint调用了OnDraw.
如果自己添加了OnPaint函数,应先加条OnPrepareDC函数调整设备上下文,然后再调用OnDraw
加入滚动条
1. 可以在新建MFC程序时从CScrollView中派生类,也可以手动修改选择VC菜单项Edit-Replace
2.
第一步做好后,当你编译运行时,程序会出错!并且不会出现滚动条,我们还要在窗口创建完毕后,我们可以添加个虚函数OnInitialUpdate()。在OnInitialUpdate()调用SetScrollSizes函数设置滚动条范围,因为OnInitialUpdate()函数是窗口创建之后所会调用的第一个函数。SetScrollSizes第一个参数是要你指定映射模式,我选择的是MM_TEXT,然后第二个参数要你传递个CSize对象,,我们可以构造一个CSize对象用于指定滚动条纵向和横向的范围!第三个参数是你指定滚动条空白栏部位被点击所滚动的数量,第四个是点击向上向下箭头滚动的范围,三四个参数为默认实参,我们不必在指定值!
void CMFC_View::OnInitialUpdate()
{
CScrollView::OnInitialUpdate();
// TODO: Add your specialized code here and/or call the base class
SetScrollSizes(MM_TEXT,CSize(1000,800));
}
编译运行一下,你会发现窗口已经具有了滚动条的功能!
滚动条的画图的问题
当你把窗口的滚动条拉到下端然后画图时!
然后只要发生了能够让窗口产生重绘消息的事件之后呢,你会发现你所画的线已经跑到了上面!
这是为什呢,为什么我们在画线条的时候没发生这种情况呢而是重绘时发生的呢?因为在窗口重绘的时候调用了OnPrepareDC(&dc);在OnPrepareDC(&dc)中调整了视口的原点!假设我们的坐标点位(893,315),此时在OnPrepareDC函数中已经将视口原点设置为了(0,-292)
我们在重绘显示图形的时候要将逻辑坐标转换为视口坐标!
根据公式:
视口X坐标=窗口X坐标-窗口X原点坐标+视口X原点
893=893-0+0
视口Y坐标=窗口Y坐标-窗口Y原点坐标+视口Y原点
23=315-0+(-292)
所以见公式,图形当然会显示在上方!
那么该如何解决呢?
我们应该在保存坐标点的前的时候调用OnPrepareDC调整视口原点!然后将调用DPtoLP设备坐标转换为逻辑坐标保存!Windows对于所有的消息用的都是设备坐标!GDI函数用逻辑坐标!
根据公式:
窗口X坐标=视口X坐标-视口X原点+窗口X原点
893=893-0+0
窗口Y坐标=视口Y坐标-视口Y原点+窗口Y原点
607=315-(-292)+0
然后在重绘将逻辑坐标映射为设备坐标时,窗口重绘再次调用OnPrepareDC再次调整市口的原点
根据公式:
视口X坐标=窗口X坐标-窗口X原点坐标+视口X原点
893=893-0+0
视口Y坐标=窗口Y坐标-窗口Y原点坐标+视口Y原点
315=607-0+(-292)
这样就刚好坐标点没变!
代码实现:
void CMFC_View::OnLButtonUp(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CClientDC dc(this);
dc.MoveTo(BegPt);
dc.LineTo(point);
OnPrepareDC(&dc);
dc.DPtoLP(&BegPt); //设备坐标转换成逻辑坐标
dc.DPtoLP(&point);
Line=new CLine;
Line->BegPt=BegPt;
Line->EndPt=point;
LineAry.Add(Line);
CScrollView::OnLButtonUp(nFlags, point);
}
最后补充下OnPrepareDC会根据滚动条的位置从而改变视口原点!所以坐标为(893,315)的线理应在移动滚动条最顶端能看见的,但是经过OnPrepareDC调整视口原点之后,就变得看不见了,只能 在原来画线的地方看见!