b et007 体育度假村哪里好入住有何要求吗 ?

至于不见了的问题简单因为当伱的窗口改变后,会产生无效区域这个无效的区域需要重画。一般Windows回发送两个消息WM_PAINT(通知

客户区有变化)和WM_NCPAINT(通知非客户区有变化)非客户区的重画系统自己搞定了,而客户区的重画需要我们自己来完成这就需要

应消息的功能。这就是为什么你用VC成的程序代码时在視图类只有OnDraw没有OnPaint的原因。

要想在屏幕上绘图或显示图形首先需要建立设备环境DC。其实DC是一个数据结构

它包含输出设备(不单指你17寸的純屏显示器,还包括打印机之类的输出设备)的绘图属性的描述MFC提供了CPaintDC类和CWindwoDC类来

实时的响应,而CPaintDC支持重画

当视图变得无效时(包括大尛的改变,移动被遮盖等等),Windows 将 WM_PAINT 消息发送给它该视图的 OnPaint 处理函数通过创建

CPaintDC 类的DC对象来响应该消息并调用视图的 OnDraw 成员函数。通常我们鈈必编写重写的 OnPaint 处理成员函数

既然OnPaint最后也要调用OnDraw,因此我们一般会在OnDraw函数中进行绘制。下面是一个典型的程序

现在大家明白这哥俩之间的關系了吧因此我们一般用OnPaint维护窗口的客户区(例如我们的窗口客户区加一个背景图片),用OnDraw维护

视图的客户区(例如我们通过鼠标在视圖中画图)当然你也可以不按照上面规律来,只要达到目的并且没有问题怎么干都成。


改变窗口大小或者窗口被遮挡(去除遮挡)時,窗口自动产生WM_PAINT消息重绘有变化的区域(无效区)
当你需要人工指定窗口重绘时,依此原理可以指定窗口客户区的某些区域无效,讓其重绘
这三个函数向窗口发送了WM_PAINT消息进入消息队列。当队列较长时(前面还有很多消息未处理)就不能即时刷新了。
你可以在上面彡个函数后加一句UpdateWindow()这样就可以立即刷新窗口了。

一款属于自己的窗体基础类库与MFC不同的是用这个类库建立的窗体形状是不规则的(用户萣义),且窗体上的所有控件都没有handle(只是

一个用户定义的region, 或者说叫hotspot)而是从一个抽象类CControl派生。由于所有可视部分都采用用户贴图(用GDI+)这样就必然要

和WM_PAINT打交道。当年用VB编程的时候对Paint事件就不甚了解,现在果然遇到了不小的问题……经过半天的研究终于基本弄明白了

WM_PAINT的来龙去脈,在这里总结一下

口的一部分被其它窗口遮盖而复原,或者从最小化状态恢复到正常状态时系统自然会要求窗口重画。系统重画窗ロ的条件可以参见MSDN

求窗口重画(通过调用UpdateWindow和RedrawWindow)比如我的基础类库里窗口上没有任何Windows意义上的控件(有hWnd),只是人为定义某

一个区域是一个“按钮”当鼠标指向这个区域时加载hover图像以获得hottrack效果。这时操作系统自然不会认为有重画的必要但程序却

必须重画,这时就得人工发送WM_PAINT消息叻注意不要傻乎乎地直接用SendMessage或PostMessage发送WM_PAINT,后面会解释原因

由于重画很费时间和资源,并且也不是应用程序的“主业”因此系统也知道要盡量减少重画的次数。系统只在应用程序的消息队列为空的

时候才发送WM_PAINT这就是为什么当程序死锁时窗口图像不会更新。同样为了减少重畫的工作量Windows提出了update region的概

region. 比如原来在窗口上面的一个窗口现在挪走了,系统就把新露出来的区域定义为update region(这个过程称为invalidate)系统不断

检测一个窗口的update region是否为空,当update region不为空并且应用程序没有消息要处理(消息队列为空)的时候系统就通过

WM_PAINT告诉应用程序“现在没事干了?窗口的一部分需要重画你把这一部分重画一下”。应用程序重画了窗口之后把update region重

新设置为空(这个过程称为validate),如此不断循环如果消息队列不为空,系统就把update region不断更新(采用取并集的方法)等消息

队列为空的时候一起处理。这就大大减少了重画的次数

这样你或许就明白了为什么不能直接用SendMessage和PostMessage发送WM_PAINT的原因:由于没有invalidate,系统认为窗口没有更新的必

各位可以自行去查MSDN.

在WM_PAINT消息处理过程中有两个不得不提到的函数:BeginPaint()和EndPaint(). 只有WM_PAINT消息处悝能使用这两个函数实际上默认

返回的DC,做好善后工作(比如重新显示BeginPaint()隐藏起来的光标)

最后还有一点需要额外说明:用WM_PAINT处理重画是异步(asynchronous)嘚。也就是说在invalidate之后窗口并不会立即重画而是等到消

息队列为空时再重画,这样就有一个时间差这个事件差有时短到不被注意,但有時就是个大问题(尤其是当程序需要执行耗费时间的任务

如串口I/O)。这时可以采用同步重画法直接用GetDC()获得hDC执行重画操作。如果非要使用WM_PAINT来哃步重画(个人比较喜欢这种方法

窗口的消息队列而不是应用程序的消息队列,这样就不用等到最后了注意前者当update region不为空时才会发送WM_PAINT,後者的控制选

对于窗口程序一般有个特点:窗口大部分的区域保持不变,只有不分区域需要重新绘制如果将整个窗口全部刷新的画,僦做了许多不必

要的工作因而,MFC采用了一套基于无效区的处理机制在分析无效区处理之前,我们要明白一个现实现在的机器还不够犇,如果够牛的

话我们干脆将整个窗口不断的重新绘制好了。事实上即使够牛也不行对于一个单线程程序,通过一个while循环不断的刷新窗口程序也

无法相应其他消息(除非使用多线程),看来使用无效区的处理机制还是有其必然性的

     VC程序是基于消息机制的,你所做的任何操作比如点击鼠标,拖动窗口首先进入系统的消息队列。这里的系统消息队列包括多个程

序的消息系统再将消息发送给相应的程序。既然是队列这就有一个先进先出的问题,屏幕上的无效区更新消息出现的频率就会特别高

比如当左上角更新的消息还没有处理,右下角更新的消息已经过来了为了避免多次处理WM_PAINT消息,系统就将这些窗口更新消息合并到

一条只是将无效区范围变成包括这两次更噺无效区范围在内的矩形区域。这样就减少了WM_PAINT消息的处理次数提高了效率。

     那么在OnPaint消息处理函数中,又是怎样实现更新无效区的呢艏先,要明白MFC中所有绘图操作都是基于设备描述表(Device

Context简称DC)的,具体信息可参看任何一本VC教材DC中包含了绘图设备的各种信息,对于屏幕绘圖其实就是有一块内存(显存),

专门用来存放要显示到屏幕上的信息显示器以85HZ的频率(我以前的显示器)将其内容刷新的屏幕上。這里就到了关键点显示器的刷新

是将显存中的内容完全更新到显示器上,不存在无效区处理的问题那么,无效区的处理一定发生在DC的繪图处理上事实确实如此,当程

序调用OnPaint消息时首先将无效区范围传递给DC,DC在进行绘图操作时就只更新无效区范围内的信息,其他地方的不管这就提高了效

WM_PAINT消息,其无效区为整个客户区而UpdateWindow直接发送一个WM_PAINT消息,其无效区范围就是消息队列中WM_PAINT消息(最多只

有一条)的无效区效果很明显,调用Invalidate之后屏幕不一定马上更新,因为WM_PAINT消息不一定在队列头部而调用UpdateWindow

会使WM_PAINT消息马上执行的,绕过了消息队列如果伱调用Invalidate之后想马上更新屏幕,那就加上UpdateWindow()这条语句

}

我要回帖

更多关于 度假村哪里好 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信