[MFC]MFC中OnDraw与OnPaint的区别
问题
问题:我在视图画的图象或者文字,当窗口改变后为什么不见了?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 重写
- 通过调用您提供的文档成员函数获取数据。
- 通过调用框架传递给 OnDraw 的设备上下文对象的成员函数来显示数据。
- 当文档的数据以某种方式更改后,必须重绘视图以反映该更改。默认的 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()等。
[MFC]MFC中OnDraw与OnPaint的区别的更多相关文章
- MFC中OnDraw()和OnPaint()的区别[转]
问题 问题:我在视图画的图象或者文字,当窗口改变后为什么不见了?OnDraw()和OnPaint()两个都是解决上面的问题,有什么不同? OnDraw()和OnPaint()好象兄弟俩,因为它们的工作 ...
- VC++中关于控件重绘函数/消息 OnPaint,OnDraw,OnDrawItem,DrawItem的区别
而OnPaint()是CWnd的类成员,同时负责响应WM_PAINT消息. OnDraw()是CVIEW的成员函数,并且没有响应消息的功能.这就是为什么你用VC成的程序代码时,在视图类只有OnDraw ...
- MFC中的Invalidate、OnDraw、OnPaint函数的作用
MFC中的Invalidate.OnDraw.OnPaint函数的作用 CWnd::Invalidate voidInvalidate( BOOL bErase = TRUE ); 该函数的作用是使 ...
- MFC程序中使用调试宏ASSERT()、ASSERT_VALID()、VERIFY()和TRACE()的区别
其实这篇文章说的很明白了:http://dev.gameres.com/Program/Other/DebugMacro.htm 结论如下: 1.ASSERT()测试它的参数,若参数为0,则中断执行并 ...
- MFC对话框中显示BMP,JPG图片
//************************************ // 方法说明: 显示JPG和GIF.BMP图片 // 参数说明: CDC * pDC 设 ...
- C++(MFC)编程中遇到的的一些函数
memset void memset( void dest, int c, size_t count ); dest: Pointer to destination c: Character to s ...
- 在MFC框架中使用OpenGL的简单实例
引言 我们知道,在MFC框架中,用于绘图的接口是GDI.但GDI只能绘制简单的2D图形,要想制作精美的3D图形,一个可行的办法是使用OpenGL或者Direct3D等第三方库. 由于最近在给导师的一个 ...
- MFC对话框中显示背景图片
在MFC对话框中显示图片,四个步骤. 1.首先得在VC6.0或者VS2008(其他版本也是一样)中导入GDI文件.(网上下载:) GDI含义是图形设备接口,主要任务是负责系统与绘图程序之间的信息交换, ...
- 《MFC dialog中加入OpenGL窗体》
<MFC dialog中加入OpenGL窗体> 最近学习了如何在MFC对话框程序中加入OpenGL窗体的方法,在这里将自己的实现过程归纳一下. 步骤零: 加入PictureControl控 ...
随机推荐
- Research on Unsupervised Word Alignment Based on Inversion Transduction Grammar
1.提出了一种基于特征函数和反向转录文法(ITG)的无监督词对齐模型,使用对数线性模型对文法规则的概率建模,先验知识可以通过特征函数的形式加入到模型里面,而模型仍然可以进行无监督训练.2. 在模型的参 ...
- php连接数据库
<?php header('Content-Type:text/html; charset=utf-8'); define('DB_HOST', 'localhost'); define('DB ...
- 最好的10本适用于初学者阅读的javaScript和jQuery书籍
现在有许多方式学习新的内容,但是对于刚开始学习和寻找真正沉迷其中的平和状态的人而言,经典的纸质书籍依旧是首选.我发现阅读一本纸质书籍会让自己远离那些在使用电脑和平板时出现的令人不安的情绪.电子书和播客 ...
- 在Cubieboard上关闭irqbalance服务避免内存泄漏
十一一个假期回来,顺手看了看自己的cubieboard运行状态怎么样 aria2正常: btsync正常: samba正常: 很好, 顺手htop一下,已经开机了13天了,CPU使用率4%,内存使用率 ...
- gem openssl 出错
Unable to require openssl, install OpenSSL and rebuild ruby (preferred) or use non-HTTPS sources 1. ...
- 主机找不到vmnet1和vmnet8
今天跑程序时,突然发现虚拟机ping不通主机了,返过来可行,防火墙什么的都设置好了,仍然不行,后来发现,在网络和共享中心已经看不到vmnet1和vmnet8了,更改适配器设置也只有本地连接和宽带连接, ...
- JavaScript 继承方式详解
js继承的概念 js里常用的如下两种继承方式: 原型链继承(对象间的继承)类式继承(构造函数间的继承) 由于js不像java那样是真正面向对象的语言,js是基于对象的,它没有类的概念.所以,要想实现继 ...
- [转]比较 Rational Unified Process (RUP) 和 Microsoft Solutions Framework (MSF)
文档选项 将此页作为电子邮件发送 级别: 初级 Sandra Sergi Santos, 软件工程专家, IBM 2007 年 6 月 15 日 本文来自于 Rational Edge:Micro ...
- Guid函数
使用GUID函数可以得到一个不重复的序列号,但是考虑到会出现并发等一系列情况,所以建议使用时间+GUID的方法去生成一串序列号 ,一般语法如下: string str = System.Guid.Ne ...
- POJ2155Matrix(二维线段树)
链接http://poj.org/problem?id=2155 题目操作就是说,每次操作可以是编辑某个矩形区域,这个区域的0改为1,1改为0,每次查询只查询某一个点的值是0还是1. 方法:二维线段树 ...