当前位置:C++技术网 > 精选软件 > Windows零基础入门:2.24 窗口类之窗口类风格CS_SAVEBITS

Windows零基础入门:2.24 窗口类之窗口类风格CS_SAVEBITS

更新时间:2015-09-20 14:55:43浏览次数:1+次

用CS_SAVEBITS风格的窗口类创建的窗口,窗口遮盖的屏幕部分或者其他窗口部分,系统将会把被遮盖的屏幕图像部分,保存为一个位图存放在内存中。当这个窗口移走后,被遮盖的屏幕部分,系统将会用之前保存的位图来恢复屏幕图像,包括被遮盖的窗口。因此,当存储的位图数据这部分内存有效并且其他屏幕上的动作没有让存储的图像失效,那么系统就不会向被遮盖的窗口发送WM_PAINT窗口重绘消息。这个风格对于小窗口,比如菜单或者对话框,是非常有用的。因为他们简单的显示并且在其他窗口活动的时候就消失。这个风格会让显示窗口的时间变长,因为系统第一次要分配内存来存储位图。     今天讲解一个窗口类风格CS_SAVEBITS。首先来说说,CS_SAVEBITS窗口类风格有什么用,会给我们窗口带来什么。
    MSDN中解释说,用CS_SAVEBITS风格的窗口类创建的窗口,窗口遮盖的屏幕部分或者其他窗口部分,系统将会把被遮盖的屏幕图像部分,保存为一个位图存放在内存中。
    当这个窗口移走后,被遮盖的屏幕部分,系统将会用之前保存的位图来恢复屏幕图像,包括被遮盖的窗口。
    因此,当存储的位图数据这部分内存有效并且其他屏幕上的动作没有让存储的图像失效,那么系统就不会向被遮盖的窗口发送WM_PAINT窗口重绘消息。
    这个风格对于小窗口,比如菜单或者对话框,是非常有用的。因为他们简单的显示并且在其他窗口活动的时候就消失。
    这个风格会让显示窗口的时间变长,因为系统第一次要分配内存来存储位图。

    我先来介绍一下基本背景知识。由前面的课程,我们知道了屏幕的刷新绘制的概念。而最终呈现在屏幕中我们看到的画面叫做屏幕图像。屏幕图像就是送给显卡去显示的整个屏幕的像素点的数据,这样的数据组成了一幅图像,因为是显示在屏幕中的,因此就是这个名称的由来。
    屏幕图像就是我们某一刻看到的静止的画面。而程序的互动,会让屏幕图像不停的改变,也就出现了交互的效果。而交互的效果的实现,需要由程序内部不停的处理WM_PAINT的窗口重绘消息来实现。
    但是,有一种情况的屏幕重绘时很没有必要的,因为这个交互并不触及程序的业务逻辑,因此,系统就提供了优化方案。那就是本课讲的这个窗口类风格的效果。

   
    我们在窗口中移动窗口,屏幕图像是在改变的,而这个改变,对于你的程序来讲,并不构成业务逻辑的交互,所以,系统就不触动你的程序窗口的重绘动作。因为这个重绘只是显示相同的画面而已,意义不大,而且显得很浪费CPU的时间。毕竟你的窗口要从头到尾画一遍,而这一遍对于前面的画面没有任何改变。
    还有一种情况,就是你的窗口被其他窗口遮盖了,然后其他窗口又移走了,那么你的窗口又显示出来了。在这个显示过程,你的窗口还是原来那样的,其实也是不需要来让你窗口去重绘的,因为没意义,根本不涉及到窗口的业务逻辑交互。
    而遮盖窗口和移动窗口都是一样的,就是不涉及到程序交互逻辑的,通常这个就是系统来处理的东西。最开始,系统就是一个初始画面,没有其他窗口。当一个窗口显示出来的时候,那么显示窗口的位置,以前的屏幕图像一部分就被遮盖了。但是,屏幕图像的被窗口覆盖的这个部分的画面,后面还会用到,比如你的窗口移走后,就要让它原样显示出来。但是如果让窗口自己去处理,显得效率比较低。因为窗口到处移来移去的,那么经过的地方,岂不是全部都要重绘一下。而且这个重绘,意义真的不大。
    所以系统在窗口显示出来前,将这个部分的图像数据保存成一个位图格式的数据,也就是二维的数组那样的数据格式,并不是说bmp图像文件哦。然后在窗口移走后,系统会用这个存储的数据恢复之前被覆盖的部分的数据。从而不必通知窗口重新绘制一下。这样就是局部的重绘了,这样是不是就让效率变高了呢?当然是的,它让重绘变得快速,让程序性能得以提升。
    而窗口移到一个新位置,新位置被覆盖,就和窗口显示出来覆盖前面一个位置的区域是一样的效果,也要让屏幕图像被覆盖的部分的数据保存起来,用于恢复。然后用移动的窗口去覆盖,最后将新的屏幕数据送给显卡显示就可以。
    这就是很多人心中一个疑惑的答案,如果你曾将疑惑过,你就知道是怎么回事了。这个疑问就是:为什么我移动窗口,并不会触发窗口重绘消息呢?当然这是有点基础的人想过的问题哈。可能一直没有找到答案吧。零基础入门的,那就现在知道就好了。
    那么并不是这种直接恢复都时刻都有效,因为系统存储的这个位图数据的内存可能会被释放,还有可能就是其他窗口可以让存储的这个图像数据设置为失效,那么这个时候,这个图像都不能再用来恢复了。举个简单的例子,比如A窗口被B窗口遮盖了一个部分,而A窗口的进程被强行终止了,那么,A窗口就不能再出来了。此时,之前存储A窗口被遮盖的部分的数据就会被设置为失效,这样就不能再用来恢复了。或者其他窗口通过API函数强行设置存储的位图数据失效,同样也会导致不能再用之前存储的数据来恢复画面。那么此时,窗口显示的时候,系统就会向被遮盖的窗口发送WM_PAINT消息,让窗口自己重绘以使之前被遮盖的位置重新画出来。
    而这个效果要实现,就是要在遮盖窗口上的窗口类中设置这个窗口类风格。你的窗口设置了这个特性,就是在告诉系统,你的窗口可能只临时性的,反正就是告诉系统,我这个窗口去过的地方,你都要临时将停留的地方的部分先存起来,我走之后,你就可以拿来快速恢复画面了。
    这个对于小窗口的菜单或者对话框或者消息框等,非常适合,因为他们很快显示,很快就会消失。它们所遮盖的位置,很快就会被恢复的,所以,系统可以快速又将屏幕图像恢复回原样,而不必惊动被遮盖的窗口。
    不过我在Win10中发现,不管是设置还是不设置,或者是在被遮盖的窗口的窗口类设置,还是在上层的那个窗口的窗口类设置,都无效,这个可能和系统的设置有关。这个我就不去铺开研究了。
    对于这个知识点,我想应该是铺开讲明白了这个道理。如果你对此有更加深入的了解,恳请告诉我一下,相互学习,我也会和大家分析出来。
    不过为了验证不同的系统不同的设置,会不会出现不设置这个窗口类就会导致被遮盖的窗口显示时会重绘,我给出了验证代码。
    代码中是注册了两个窗口类,创建了两个窗口。第一个窗口就是常规的窗口,第二个窗口就是带了这个窗口类风格的窗口。然后两个窗口有两个窗口过程,分别用全局变量来计数,刷新一次窗口累加,然后就可以增加显示文字的个数,以此来验证窗口是否重绘了。
    验证的方法就是,用第二个窗口遮盖一下主窗口,然后移开,看看主窗口会不会显示多一个文字,如果可以,那表示导致了重绘,如果不可以,表示没有导致重绘。然后你可以去掉第二个窗口类的CS_SAVEBITS风格,再看看会不会导致重绘。
    按理来说,设置了这个风格的,是不会导致重绘的,没有设置的,会导致重绘。不过要看系统的具体设置,很多系统的特性被一些卫士软件优化过或者自己设置过,可能就体现不出来了。具体原因,还需要调查。不过不影响大家了解这个知识内容。
    如果有任何问题或者建议,或者补充,请留言哦。