WM_PAINT与其响应函数OnPaint(VC++)


On Paint()是CWnd的类成员,负责响应WM_PAINT消息,在On Paint中调用On Draw,一般来说,用户自己的绘图代码应放在On Draw中。On Draw()是CVIEW的成员函数,没有响应消息的功能.当视图 变得无效时(包括大小的改变,移动,被遮盖等等),Windows发送WM_PAINT消息。该视图的On Paint 处理函数通过创建CPaintDC类的DC对象来响应该消息并调用视图的On Draw成员函数.On Paint最后也要调用On Draw,因此一般在 On Draw函数中进行绘制。在On Paint中,将调用BeginPaint,用来获得客户区的显示设备环境,并以此调用GDI函数执行绘图操作。在绘图操作完成后,将调用EndPaint以释放显示设备环境。而On Draw在BeginPaint与EndPaint间被调用。1) 在mfc结构里On Paint是CWnd的成员函数. On Draw是CView的成员函数.
   On Paint()调用On Draw(),On Print也会调用On Draw(),所以On Draw()是显示和打印的共同操作。
On Paint是WM_PAINT消息引发的重绘消息处理函数,在On Paint中会调用On Draw来进行绘图。On Paint中首先构造一个CPaintDC类得实 例,然后一这个实例为参数来调用虚函数On PrepareDC来进行一些绘制前的一些处理,比设置映射模式,最后调用On Draw。而On Draw和 On PrepareDC不是消息处理函数。所以在不是因为重绘消息所引发的On Paint导致On Draw被调用时,比如在On LButtonDown等 消息处理函数中绘图时,要先自己调用On PrepareDC。
至于CPaintDC和CClientDC根本是两回事情 CPaintDC是一个设备环境类,在On Paint中作为参数传递给On PrepareDC来作设备环境的设置。真正和CClientDC具有可比性的 是CWindowDC,他们一个是描述客户区域,一个是描述整个屏幕。
如果是对CVIEW或从CVIEW类派生的窗口绘图时应该用On Draw。On Draw()和On Paint()有什么区别呢?
首先:我们先要明确CView类派生自CWnd类。而On Paint()是 CWnd的类成员,同时负责响应WM_PAINT消息。On Draw()是CVIEW的成员函数,并且没有响应消息的功能。这就是为什么你用VC成的程序 代码时,在视图类只有On Draw没有On Paint的原因。而在基于对话框的程序中,只有On Paint。
   要想在屏幕上绘图或显示图形,首先需要建立设备环境DC。其实DC是一个数据结构,它包含输出设备(不单指你17寸的纯屏显示 器,还包括打印机之类的输出设备)的绘图属性的描述。MFC提供了CPaintDC类和CWindwoDC类来实时的响应,而CPaintDC支持重画。 当视图变得无效时(包括大小的改变,移动,被遮盖等等),Windows 将 WM_PAINT 消息发送给它。该视图的On Paint 处理函数通过创建 CPaintDC 类的DC对象来响应该消息并调用视图的 On Draw 成员函数。通常我们不必编写重写的 On Paint 处理成员函数。
///CView默认的标准的重画函数
void CView::On Paint() //见VIEWCORE.CPP
{CPaintDC dc(this);
On PrepareDC(&dc);
On Draw(&dc);   //调用了On Draw
}
///CView默认的标准的On Print函数
void CView::On Print(CDC* pDC, CPrintInfo*)
{
ASSERT_VALID(pDC);
On Draw(pDC); // Call Draw
}既然On Paint最后也要调用On Draw,因此我们一般会在On Draw函数中进行绘制。下面是一个典型的程序。
///视图中的绘图代码首先检索指向文档的指针,然后通过DC进行绘图调用。
void CMyView::On Draw( 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() );
}
    因此我们一般用On Paint维护窗口的客户区(例如我们的窗口客户区加一个背景图片),用On Draw维护视图 的客户区(例如我们通过鼠标在视图中画图)。当然你也可以不按照上面规律来,只要达到目的并且没有问题,怎么干都成。补充:我们还可以利用 Invalidate(),ValidateRgn(),ValidateRect()函数强制的重画窗口,具体的请参考MSDN吧。On Draw中可以绘制用户区域。On Paint中只是当窗口无效时重绘不会保留CClientDC绘制的内容。这两个函数有区别也有联系:1、区别:On Draw是一个纯虚函数,定义为virtual void On Draw( CDC* pDC ) = 0; 而On Paint是一个消息响应函数,它响应了WM_PANIT消息,也是是窗口重绘消息。2、联系:我们一般在视类中作图的时候,往往不直接响应WM_PANIT消息,而是重载On Draw纯虚函数,这是因为在CVIEW类中的 WM_PANIT消息响应函数中调用了On Draw函数,如果在CMYVIEW类中响应了WM_PAINT消息,不显式地调用On Draw函数的话,是不 会在窗口重绘的时候调用On Draw函数的。应用程序中几乎所有的绘图都在视图的 On Draw 成员函数中发生,必须在视图类中重写该成员函数。(鼠标绘图是个特例,这在通过视图解释用户输入中讨论。)On Draw 重写:
通过调用您提供的文档成员函数获取数据。
通过调用框架传递给 On Draw 的设备上下文对象的成员函数来显示数据。
当 文档的数据以某种方式更改后,必须重绘视图以反映该更改。默认的 On Update 实现使视图的整个工作区无效。当视图变得无效时,Windows 将 WM_PAINT 消息发送给它。该视图的 On Paint 处理函数通过创建 CPaintDC 类的设备上下文对象来响应该消息并调用视图的 On Draw 成员函数。

当没有添加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()等。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值