问题

问题:我在视图画的图象或者文字,当窗口改变后为什么不见了?OnDraw()和OnPaint()两个都是解决上面的问题,有什么不同?

OnDraw()和OnPaint()好象兄弟俩,因为它们的工作类似。

至于不见了的问题简单,因为当你的窗口改变后,会产生无效区域,这个无效的区域需要重画。一般Windows回发送两个消息WM_PAINT(通知客户区 有变化)和WM_NCPAINT(通知非客户区有变化)。非客户区的重画系统自己搞定了,而客户区的重画需要我们自己来完成。这就需要OnDraw()或 OnPaint()来重画窗口。

OnDraw()和OnPaint()有什么区别呢?

1.OnPaint()是CWnd的类成员,是一个消息响应函数,负责响应WM_PAINT消息。OnDraw()是CVIEW的成员函数,没有响应消息的功能.是一个纯虚函数,定义为virtual void OnDraw( CDC* pDC ) = 0;

当视图变得无效时(包括大小的改变,移动,被遮盖等等),Windows发送WM_PAINT消息。该视图的OnPaint 处理函数通过创建CPaintDC类的DC对象来响应该消息并调用视图的OnDraw成员函数.

OnPaint()是CWnd的类成员,负责响应WM_PAINT消息。OnDraw()是CVIEW的成员函数,没有响应消息的功能.当视图变得无效时(包括大小的改变,移动,被遮盖等等),Windows发送WM_PAINT消息。该视图的OnPaint 处理函数通过创建CPaintDC类的DC对象来响应该消息并调用视图的OnDraw成员函数.

我们先要明确CView类派生自CWnd类。而OnPaint()是CWnd的类成员,同时负责响应WM_PAINT消息。OnDraw()是CVIEW的成员函数,并且没有响应消息的功能。这就是为什么你用VC写的程序代码时,在视图类只有OnDraw没有OnPaint的原因。而在基于对话框的程序中,只有OnPaint。

2.OnPaint()调用OnDraw(),OnPrint也会调用OnDraw(),所以OnDraw()是显示和打印的共同操作。 

CView封装了两个函数,OnPaint()与OnPrint(),分别对应WM_PAINT与WM_PRINT。MFC为了提供更标准简易的编程接口,所以又提供了OnDraw()这个函数。OnDraw()将被OnPaint()或OnPrint()调用,根据二者分别传进来的不同DC(Paint DC或Print DC),从而完成屏幕绘制或打印工作,而不需再为两种情况分别写代码。当然,如果你只关心屏幕绘制工作,而不关心打印问题,那你完全可以直接重载OnPaint()完成绘制,而不使用OnDraw()。

Invalidate()和InvalidateRect()其实是触发对onPaint()函数的调用,OnPaint()函数调用OnDraw()函数,OnDraw函数还需要同时支持打印机输出。OnPaint()函数和OnPrint()函数都要调用OnDraw(),于是同样的绘图代码既可以用于屏幕输出,也可以用于打印机输出。在编程中,一般重载OnDraw()就可以了。如果定义了OnPaint()函数,并且在OnDraw()里面有要显示的内容,那么需要显示的调用OnDraw(),即OnDraw(&dc)。

///CView默认的标准的重画函数 
void CView::OnPaint() //见VIEWCORE.CPP 

CPaintDC dc(this); 
OnPrepareDC(&dc);
OnDraw(&dc); //调用了OnDraw 

///CView默认的标准的OnPrint函数 
void CView::OnPrint(CDC* pDC, CPrintInfo*) 

ASSERT_VALID(pDC); 
OnDraw(pDC); // Call Draw 
}
 
//既然OnPaint最后也要调用OnDraw,因此我们一般会在OnDraw函数中进行绘制。下面是一个典型的程序。 
///视图中的绘图代码首先检索指向文档的指针,然后通过DC进行绘图调用。 
void CMyView::OnDraw( CDC* pDC ) 

CMyDoc* pDoc = GetDocument(); 
CString s = pDoc->GetData(); 
GetClientRect( &rect ); // Returns a CString CRect rect; 
pDC->SetTextAlign( TA_BASELINE | TA_CENTER ); 
pDC->TextOut( rect.right / 2, rect.bottom / 2, s, s.GetLength() ); 

//现在大家明白这哥俩之间的关系了吧。
//因此我们一般用OnPaint维护窗口的客户区(例如我们的窗口客户区加一个背景图片);
//用OnDraw维护视图的客户区(例如我们通过鼠标在视图中画图)。
//补充:我们还可以利用Invalidate(),ValidateRgn(),ValidateRect()函数强制的重画窗口

3.OnDraw中可以绘制用户区域。OnPaint中只是当窗口无效时重绘不会保留CClientDC绘制的内容。 

4.我们一般在视类中作图的时候,往往不直接响应WM_PANIT消息,而是重载OnDraw纯虚函数,这是因为在CVIEW类中的WM_PANIT消息响应函数中调用了OnDraw函数,如果在CMYVIEW类中响应了WM_PAINT消息,不显式地调用OnDraw函数的话,是不会在窗口重绘的时候调用OnDraw函数的。 应用程序中几乎所有的绘图都在视图的  OnDraw  成员函数中发生,必须在视图类中重写该成员函数。

OnDraw 重写

  1. 通过调用您提供的文档成员函数获取数据。
  2. 通过调用框架传递给 OnDraw 的设备上下文对象的成员函数来显示数据。
  3. 当文档的数据以某种方式更改后,必须重绘视图以反映该更改。默认的 OnUpdate 实现使视图的整个工作区无效。当视图变得无效时,Windows 将 WM_PAINT 消息发送给它。该视图的 OnPaint 处理函数通过创建 CPaintDC 类的设备上下文对象来响应该消息并调用视图的 OnDraw 成员函数。
  • 当没有添加WM_PAINT消息处理时,窗口重绘时,由OnDraw来进行消息响应...
  • 当添加WM_PAINT消息处理时,窗口重绘时,WM_PAINT消息被投递,由OnPaint来进行消息响应.这时就不能隐式调用OnDraw了.必须显式调用( CDC *pDC=GetDC(); OnDraw(pDC); )..
  • 隐式调用:当由OnPaint来进行消息响应时,系统自动调用CView::OnDraw(&pDC).

想象一下,窗口显示的内容和打印的内容是差不多的,所以,一般情况下,统一由OnDraw来画。窗口前景需要刷新时,系统会会调用到OnPaint,而OnPaint一般情况下是对DC作一些初始化操作后,调用OnDraw()。 
OnEraseBkGnd(),是窗口背景需要刷新时由系统调用的。明显的一个例子是设置窗口的背景颜色(你可以把这放在OnPaint中去做,但是会使产生闪烁的现象)。至于怎么界定背景和前景,那要具体问题具体分析了,一般情况下,你还是很容易区别的吧。 
的确,OnPaint()用来响应WM_PAINT消息,视类的OnPaint()内部根据是打印还是屏幕绘制分别以不同的参数调用OnDraw()虚函数。所以在OnDraw()里你可以区别对待打印和屏幕绘制。 
其实,MFC在进行打印前后还做了很多工作,调用了很多虚函数,比如OnPreparePrint()等。 

 
转自:http://www.cnblogs.com/suncoolcat/p/3285620.html
 

MFC中OnDraw()和OnPaint()的区别[转]的更多相关文章

  1. [MFC]MFC中OnDraw与OnPaint的区别

    问题 问题:我在视图画的图象或者文字,当窗口改变后为什么不见了?OnDraw()和OnPaint()两个都是解决上面的问题,有什么不同? OnDraw()和OnPaint()好象兄弟俩,因为它们的工作 ...

  2. MFC中 Invalidate() , InvalidateRect() , UpdateWindow(), Redrawwindow() 区别

    1. void Invalidate( BOOL bErase = TRUE ); 该函数的作用是使整个窗口客户区无效.窗口的客户区无效意味着需要重绘,例如,如果一个被其它窗口遮住的窗口变成了前台窗口 ...

  3. MFC中ON_COMMAND,ON_MESSAGE,ON_NOTIFY的区别

    原文链接地址:https://blog.csdn.net/sufwei/article/details/3635489 ON_COMMAND //用来响应相应工具栏和菜单栏的命令WM_COMMAND, ...

  4. MFC中ON_UPDATE_COMMAND_UI和ON_COMMAND消息区别

    原文链接地址:http://www.cnblogs.com/orez88/articles/2217823.html 第一个是你打开这个菜单时,处理这个菜单的状态,比如选中.变灰等等.  第二个是响应 ...

  5. MFC中onmouseover与onmousemove的区别

    onmouseover与onmousemove的区别是:当鼠标移过当前对象时就产生了onmouseover事件,当鼠标在当前对象上移动时就产生了onmousemove事件,只要是在对象上移动而且没有移 ...

  6. MFC中L, _T(),TEXT,_TEXT区别以及含义

    字符串前面加L表示该字符串是Unicode字符串. _T是一个宏,如果项目使用了Unicode字符集(定义了UNICODE宏),则自动在字符串前面加上L,否则字符串不变.因此,Visual C++里边 ...

  7. VC++中关于控件重绘函数/消息 OnPaint,OnDraw,OnDrawItem,DrawItem的区别

    而OnPaint()是CWnd的类成员,同时负责响应WM_PAINT消息. OnDraw()是CVIEW的成员函数,并且没有响应消息的功能.这就是为什么你用VC成的程序代码时,在视图类只有OnDraw ...

  8. MFC中的Invalidate、OnDraw、OnPaint函数的作用

    MFC中的Invalidate.OnDraw.OnPaint函数的作用 CWnd::Invalidate voidInvalidate( BOOL bErase = TRUE ); 该函数的作用是使 ...

  9. 关于MFC中的OnPaint和OnDraw

    当窗口发生改变后,会产生无效区域,这个无效的区域需要重画. 一般Windows会发送两个消息WM_PAINT(通知客户区 有变化)和WM_NCPAINT(通知非客户区有变化). 非客户区的重画系统自己 ...

随机推荐

  1. 【英语】Bingo口语笔记(45) - Pass系列

  2. java-过滤器-监听器-拦截器

    1.过滤器 Servlet中的过滤器Filter是实现了javax.servlet.Filter接口的服务器端程序,主要的用途是过滤字符编码.做一些业务逻辑判断等.其工作原理是,只要你在web.xml ...

  3. SQL Server 2008 序列号

    SQL Server 2008 序列号:Developer: PTTFM-X467G-P7RH2-3Q6CG-4DMYBEnterprise:   JD8Y6-HQG69-P9H84-XDTPG-34 ...

  4. PHP中的session

    来自博客园 1.初始化(使用session前都要使用,一个页面用一个就可以了) session_start(); 2.保存 $_SESSION[$sessionName]=$value; (value ...

  5. Python在centos下的安装

    1.wget http://www.python.org/ftp/python/2.7.9/Python-2.7.9.tgz默认下载到主目录下 2.tar xzf Python-2.6.6.tgz 3 ...

  6. OpenGl从零开始之坐标变换(下)

    这节主要来理解投影变换和视口变换的使用. 1.正射投影:glOrtho 函数原型: void glOrtho(GLdouble left,GLdouble right,GLdouble bottom, ...

  7. 数往知来JavaScript_DOM<十>

    一.DOM   1.onclick事件 表示点击 一般用在-->跳转 a标签,希望点击的时候不去跳转,而是做别的事情,并在里面返回一个false <a href="http:// ...

  8. 【重读】The C++ Programming Language/C++编程语言(一)

    最近在写C++系列的文章,翻出以前看过的 C++之父Bjarne Stroustrup的书.再一次,竟然又有新的领悟.现在看来,这不是一本只讲C++的书,对于程序设计/开发,以及如何学习开发知识都有所 ...

  9. AWS Summit 2014 San Francisco站总结

    我上个月去San Francisco参加了AWS Summit 2014 会议,总结一下参加这个会议的情况. 什么是AWS Summit? AWS Summit 是AWS在全球各地举办的,针对AWS用 ...

  10. URAL-1997 Those are not the droids you're looking for 二分匹配

    题目链接:http://acm.timus.ru/problem.aspx?space=1&num=1997 题意:记录了n个人进出门的时间点,每个人在房子里面待的时间要么小于等于a,要么大于 ...