OnPaint和OnDraw有什么区别

OnPaint和OnDraw有什么区别?

CPaintDC和CClientDC又有什么区别? 

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

1) 在mfc结构里 OnPaint是CWnd的成员函数. OnDraw是CView的成员函数.
2) OnPaint()调用OnDraw(),OnPrint也会调用OnDraw(),所以OnDraw()是显示和打印的共同操作。 
OnPaint是WM_PAINT消息引发的重绘消息处理函数,在OnPaint中会调用OnDraw来进行绘图。 OnPaint中首先构造一个CPaintDC类得实例,然后以这个实例为参数来调用虚函数OnPreapreDC来进行一些绘制前的一些处理,比如设置映射模式,最后调用OnDraw。
而OnDraw和OnPreapreDC不是消息处理函数。 所以不是因为重绘消息所引发的。OnPaint导致OnDraw被调用时,比如在OnLButtonDown等消息处理函数中绘图时,要先自己调用OnPreapreDC。 
至于CPaintDC和CClientDC根本是两回事情。CPaintDC是一个设备环境类,在OnPaint中作为参数传递给OnPreapreDC来作设备环境的设置。真正和CClientDC具有可比性的是CWindowDC,它们一个是描述客户区域,一个是描述整个屏幕。
如果是对CView或从CView类派生的窗口绘图时应该用OnDraw()。 


OnDraw()和OnPaint()有什么区别呢?
首先:我们先要明确CView类派生自CWnd类。而OnPaint()是CWnd的类成员,同时负责响应WM_PAINT消息。OnDraw()是CVIEW的成员函数,并且没有响应消息的功能。这就是为什么你用VC生成程序代码时,在视图类只有OnDraw没有OnPaint的原因。
  其次:我们在《每天跟我学MFC》3的开始部分已经说到了。要想在屏幕上绘图或显示图形,首先需要建立设备环境DC。其实DC是一个数据结构,它包含输出设备(不单指你17寸的纯屏显示器,还包括打印机之类的输出设备)的绘图属性的描述。MFC提供了CPaintDC类和CWindwoDC类来实时的响应,而CPaintDC支持重画。 当视图变得无效时(包括大小的改变,移动,被遮盖等等),Windows 将 WM_PAINT 消息发送给它。该视图的 OnPaint 处理函数通过创建 CPaintDC 类的DC对象来响应该消息并调用视图的 OnDraw 成员函数。通常我们不必编写重写的 OnPaint 处理成员函数。
//CView默认的标准的重画函数 
void CView::OnPaint() 
{
CPaintDC dc(this);
OnPrepareDC(&dc);
OnDraw(&dc); //调用了OnDraw 
}
既然OnPaint最后也要调用OnDraw,因此我们一般会在OnDraw函数中进行绘制。下面是一个典型的程序 
//视图中的绘图代码首先检索指向文档的指针,然后通过DC进行绘图调用。 
void CMyView::OnDraw( CDC* pDC )
{
CMyDoc* pDoc = GetDocument();
CString s = pDoc->GetData(); // Returns a CString 
CRect rect; 
GetClientRect( &rect ); 
pDC->SetTextAlign( TA_BASELINE | TA_CENTER ); 
pDC->TextOut( rect.right / 2, rect.bottom / 2, s, s.GetLength() );

最后:现在大家明白这哥俩之间的关系了吧。因此我们一般用OnPaint维护窗口的客户区(例如我们的窗口客户区加一个背景图片),用OnDraw维护视图的客户区(例如我们通过鼠标在视图中画图)。当然你也可以不按照上面规律来,只要达到目的并且没有问题,怎么干都成。 补充:我们还可以利用Invalidate(),ValidateRgn(),ValidateRect()函数强制的重画窗口,具体的请参考MSDN吧 
ondraw中可以绘制用户区域 onpaint中只是当窗口无效时重绘不会保留CClientDC绘制的内容 .

基本基类----CView类中含有三个方法:

1,虚函数OnPrint()

2,基本消息响应函数OnPaint(),非虚函数

3,虚函数OnDraw()

一般在我们创建Doc/View应用程序时,视图类的基类多数为CView类,或者其派生类,因此,在我们的应用程序中的View类中就继承了其父类的上面的三个方法,但是,在我们使用classwizard生成应用程序的框架的时候,向导只为我们的View类override了OnDraw()方法。其余两个方法没有生成。程序运行时,在输出显示(向显示器输出或者向打印机输出)之前,应用程序自动发出WM_PAINT消息,此时,我们的应用程序会调用我们的View类中的OnPaint()或者OnPrint()方法,但是,我们View类中并没有override其实现代码,因而调用其基类的相应的 OnPaint()或者OnPrint()方法,下面进行分类:

1在向显示器输出时,调用的是OnPaint()方法,而OnPaint()方法默认情况下会调用OnDraw()来具体动作,即向显示器输出具体的内容

2在向打印机输出时,调用的是OnPrint()方法,而OnPrint()方法默认情况下同样调用OnDraw()来具体动作,即向打印机输出具体内容

而实际上,我们只有一个已经实现了具体代码的OnDraw()方法,因此在向显示器输出和向打印机输出时的具体动作是一样的,也就是具体的输出方式和输出内容都是一样的。

那么OnPaint()和OnPrint()难道只调用OnDraw来实际动作,还要这连个函数干吗呢,不如直接用OnDraw不就完了吗?实际情况并非如此,分析如下:

1OnPaint()方法在调用OnDraw方法向显示器输出之前需要做大量的准备工作,其中之一就是准备一个跟显示器相关的DC对象,并把此对象传递给OnDraw方法,让其用此对象向显示器输出

2OnPrint()方法在调用OnDraw方法向打印机输出之前同样作很多准备工作,其中之一就是准备一个跟打印机相关的DC对象,并把此对象传递给OnDraw方法,让其用此对象向打印机输出。

因此,尽管主调函数不同,传入的参数也不同,但是对于OnDraw方法来说,这个DC对象是毫无差别的,只是一个用来画内容的工具,在其具体动作时,根本不区分是何种对象,因此也就实现了设备的无关性。具体流程如下图:



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

我们还可以利用Invalidate()(不一定马上重绘,优先级比较低。UpDateWindow()可立即引起重绘),ValidateRgn(),ValidateRect()函数强制的重画窗口

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值