| 
 | 
 
 
 楼主 |
发表于 2009-5-20 10:09:53
|
显示全部楼层
 
 
 
C++中如何实现窗口重绘并避免闪烁现象
  C++中如何实现窗口重绘并避免闪烁现象 
  学习了才知道编程远非想像的那么简单,比如我们平时在电脑里看到的窗口被遮住或最小化之后,窗口里的内容是不会丢失的,这是一件最普通平常的事情了,但就是么这一件看似很简单自然的窗口重绘事情,实现起来却是很麻烦的,非可视化的编程软件似乎没有提供这种现成的设置,只能由程序员自己来实现。比如你在窗口里写上字,画上图,然后当你的窗口被其他窗口覆盖后,你窗口里的内容就会被抹掉,系统是不会帮你重画的,这时为了保证窗口里内容的完整性,你必须对窗口里的内容进行重画,而这个重画的工作只能由程序员自己来做。 
  最简单的做法是在程序收到系统发送过来的WM_PAINT窗口重绘消息时,把窗口里原来的内容再画一遍,这对于简单的文字和图画是比较简便可行的办法,但假如你显示的是一张地图,甚至是动态的图片,那就很麻烦了。而且重画期间,窗口还会出现闪烁现象,重画的频率越高,闪烁就越厉害,如果用这种方法来写游戏,无疑是很难行得通的。为此,我请教了很多高手,在很多QQ群里问了很多前辈,也在很多编程论坛上发过很多求教的贴子,都没有得到满意的答案。于是我决定自己来实现这一功能,终于经过两天的研究,我自己实现了不论在什么情况下,都能使窗口的内容保持原样,即使窗口被频繁的改变大小、移动或遮盖,也能使窗口里的内容保持原样并不会出现闪烁现象的功能。 
  我的设计思路是这样的:①在填充窗口类的时候,把窗口的背景刷设为空(可以避免出现闪烁现象,但不会自动擦除窗口内容);②在内存中开辟一块虚拟的后台显示区,把要显示在窗口中的内容先写到这个后台中;③用BitBlt()函数把内存后台显示区中的内容整块传送给窗口显示出来,然后在每次收到系统发送过来的WM_PAINT窗口重绘消息时,都使用一次BitBlt()函数把内存后台显示区中的内容整块传送给窗口,这样的效果就非常好了。 
  思路看起来并不复杂,但实现起来也不轻松,下面是源代码及注释: 
 
HDC hdcmem;                         //定义后台内存显示设备句柄,这个要在主函数WinMain()外定义成全局变量,用以始终保持窗口内容。 
                                                              
//下面是显示完窗口以后的程序     
HDC hdc;                                          //定义窗口设备句柄变量 
HBITMAP hBitmap;                             //定义一个位图句柄变量 
hdc=GetDC(hwnd);                             //获得窗口客户区显示设备句柄 
hdcmem=CreateCompatibleDC(hdc);      //建立一个与实际设备兼容的内存设备  
hBitmap = CreateCompatibleBitmap(hdc,600,800);  
                                                      //创建与指定的设备环境相关的兼容位图,第一个参数是设备环境句柄; 
                                                      //第二个参数是位图的宽度,第三个参数是位置的高度。  
 
SelectObject(hdcmem,hBitmap);           //该函数选择一对象到指定的设备环境中,第 
                                                      //一个参数是指定设备的句柄,第二个参数是 
                                                      //被选对象的句柄。只有先对内存显示设备句 
                                                      //柄选入位图对象,才能对其进行画图操作。  
TextOut(hdcmem,100,100,"很好!",strlen("很好!"));   //往后台进行写操作或画图,想显示什么内容自己决定。 
BitBlt(hdc,0,0,600,800,hdcmem,0,0,SRCCOPY);            //把后台的内容整块复制显示到窗口中 
ReleaseDC(hwnd,hdc);                                             //释放显示器句柄 
 
//下面是收到系统发送过来的WM_PAINT窗口重绘消息时的处理程序。 
case WM_PAINT:  
       hdc=BeginPaint(hwnd,&ps);                               //BeginPaint()和下面的EndPaint()是处理WM_PAINT消息的典型做法,这里不详细介绍。 
                                                                          //PS和HDC必须在回调函数里的前面重新定义,其中PS要定义成PAINTSTRUCT类型。 
       BitBlt(hdc,0,0,600,800,hdcmem,0,0,SRCCOPY);    //重新把内存中的内容显示到窗口 
       EndPaint(hwnd,&ps);  
       break; 
 
  上面程序还不太完善,但已经能实现想要的功能了。这里不是编程交流区,可能大家对编程不是很熟悉,我就当学习日记一样的写出来,希望编程高手指导,太希望有一个好的老师了。 
 
[ 本帖最后由 czy7812 于 2009-5-20 10:28 编辑 ] |   
 
 
 
 |