您的位置:首页 > 大数据 > 人工智能

Onpaint和OnDraw的区别[转]

2009-10-08 23:44 330 查看

Onpaint
OnDraw
区别
[转]

OnPaint
是WM_PAINT消息的消息处理函数,在OnPaint
中调用OnDraw
,一般来说,用户自己的绘图代码应放在OnDraw
中。
OnPaint
()是CWnd的类成员,负责响应WM_PAINT消息。OnDraw
()是CVIEW的成员函数,没有响应消息的功能.当视图变得无效时(包括大小的改变,移动,被遮盖等等),Windows发送WM_PAINT消息。该视图的OnPaint
处理函数通过创建CPaintDC类的DC对象来响应该消息并调用视图的OnDraw
成员函数.OnPaint
最后也要调用OnDraw
,因此一般在OnDraw
函数中进行绘制。
The WM_PAINT message is sent when the UpdateWindow or RedrawWindow member function is called.
OnPaint
中,将调用BeginPaint,用来获得客户区的显示设备环境,并以此调用GDI函数执行绘图操作。在绘图操作完成后,将调用EndPaint以释放显示设备环境。而OnDraw
在BeginPaint与EndPaint间被调用。
1) 在mfc结构里OnPaint
是CWnd的成员函数. OnDraw
是CView的成员函数.

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

OnPaint
是WM_PAINT消息引发的重绘消息处理函数,在OnPaint
中会调用OnDraw
来进行绘图。OnPaint
中首先构造一个CPaintDC类得实例,然后一这个实例为参数来调用虚函数OnPrepareDC来进行一些绘制前的一些处理,比设置映射模式,最后调用OnDraw
。而OnDraw
和OnPrepareDC不是消息处理函数。所以在不是因为重绘消息所引发的OnPaint
导致OnDraw
被调用时,比如在OnLButtonDown等消息处理函数中绘图时,要先自己调用OnPrepareDC。

至于CPaintDC和CClientDC根本是两回事情 CPaintDC是一个设备环境类,在OnPaint
中作为参数传递给OnPrepareDC来作设备环境的设置。真正和CClientDC具有可比性的是CWindowDC,他们一个是描述客户区域,一个是描述整个屏幕。

如果是对CVIEW或从CVIEW类派生的窗口绘图时应该用OnDraw

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

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



次:我们在第《每天跟我学MFC》3的开始部分已经说到了。要想在屏幕上绘图或显示图形,首先需要建立设备环境DC。其实DC是一个数据结构,它包含输出
设备(不单指你17寸的纯屏显示器,还包括打印机之类的输出设备)的绘图属性的描述。MFC提供了CPaintDC类和CWindwoDC类来实时的响
应,而CPaintDC支持重画。当视图变得无效时(包括大小的改变,移动,被遮盖等等),Windows 将 WM_PAINT
消息发送给它。该视图的OnPaint
处理函数通过创建 CPaintDC 类的DC对象来响应该消息并调用视图的 OnDraw
成员函数。通常我们不必编写重写的 OnPaint
处理成员函数。

///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()函数强制的重画窗口,具体的请参考MSDN吧。
OnDraw
中可以绘制用户区域。OnPaint
中只是当窗口无效时重绘不会保留CClientDC绘制的内容。
这两个函数有区别
也有联系:
1、区别
OnDraw
是一个纯虚函数,定义为virtual void OnDraw
( CDC* pDC ) = 0; 而OnPaint
是一个消息响应函数,它响应了WM_PANIT消息,也是是窗口重绘消息。
2、联系:我们一般在视类中作图的时候,往往不直接响应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()等。
对于OnDraw
()

This method is called by the framework to render an image of the
document. The framework calls this method to perform screen display,
printing, and print preview, and it passes a different device context
in each case. There is no default implementation.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: