VC双缓冲技术绘图

  在图形图像处理编程过程中,双缓冲是一种基本的技术。如果窗体在响应WM_PAINT消息的时候要进行复杂的图形处理,那么窗体在重绘是由于过于频繁的刷新而出现闪烁现象。解决这一问题的有效方法就是双缓冲技术。

      因为窗体在刷新时,总要有一个擦除原来图像的过程OnEraseBkgnd,它利用背景色填充窗体绘图区,即重绘背景,然后再调用新的绘图代码进行重绘,这样一擦一写就造成了图像颜色的反差。当WM_PAINT消息响应很频繁时,这种反差也就越明显,这样就会出现闪烁现象。

      禁止重绘背景固然可以消除反差,但也会导致窗体内容的混乱,即原先的图像残留得不到清除,窗体内容无法完全更新。因此,不能单纯禁止重绘背景来解决闪烁现象。为了消除闪烁现象而不降低绘图速度,这里就需要利用双缓冲的思想了。

      双缓冲的思路是:在内存中创建缓冲DC(后台DC),把要显示的图形图像绘制到内存缓冲DC中,然后利用BitBlt函数将内存缓冲DC的图像复制到最终的显示DC(前台DC)上。由于BitBlt的复制操作速度非常快,与原先的绘制操作相比,几乎不会增加绘图显示时间。与此同时,禁止背景重绘。这样既消除了闪烁现象,也几乎不影响绘图显示速度。

 

      具体操作如下:

一、禁止背景重绘

      CView类的WM_ERASEBKGND消息响应函数实现了重绘背景的功能。这里在工程的视图类中添加该响应函数,并将其默认代码(调用CView类的OnEraseBkgnd()函数)注释掉,令其不做任何处理,直接返回TRUE即可。

二、在OnDraw或OnPaint中实现双缓冲

 1、创建缓冲DC

[cpp]  view plain copy
  1. CRect   rect;              // 存储客户区大小  
  2. CDC     MemDC;             // 用于缓冲绘图的内存DC  
  3. CBitmap MemBitmap ;        // 内存DC中承载临时图像的位图  
  4.   
  5. // 获取当前客户区大小  
  6. GetClientRect( &rect );   
  7.       
  8. // 创建兼容当前DC的内存DC  
  9. MemDC.CreateCompatibleDC( pDC );  
  10.   
  11. // 创建兼容位图  
  12. MemBitmap.CreateCompatibleBitmap( pDC, rect.Width(), rect.Heigth() );  
  13.   
  14. // 将兼容位图选入到内存缓冲DC,相当于画布,必须选进内存DC  
  15. MemDC.SelectObject( &MemBitmap );   
  16.   
  17.  // 使用原背景色填充内存缓冲DC  
  18. MemDC.FillSolidRect( rect, pDC->GetBkColor() );   

     注意:CreateCompatibleBitmap的第一个参数必须是当前DC,而不能是内存DC。否则创建的位图将是黑白单色位图,要创建彩色位图,必须使用当前DC指针pDC。

2、将图像图像绘制到内存缓冲DC中

       将绘图代码中的“pDC->”全部改为“MemDC.”即可。

3、将内存缓冲DC中的内容复制到当前DC

[c-sharp]  view plain copy
  1. pDC->BitBlt( 0,0,rect.Width().rect.Height(),&MemDC,0,0,SRCCOPY );  

 

      经过这样的处理,无论窗体如何变化,窗体内容都不会再出现闪烁现象。

      值得注意的是,如果图形绘制需要的时间不多(步骤二、2),上述方法的防闪烁效果非常好。但如果图形绘制需要的时间较多,比如2或3秒甚至更多,上述方法就会产生一个问题:窗体内容会在相应的时间内(2或3秒甚至更多)没有变化,呈现假死机现象。

      不使用双缓冲时,随着图形绘制代码的执行,窗体会将每一个图形逐个显示出来,虽然有点闪烁,但对用户来说,程序还在执行,没有死机。而使用双缓冲后,图形是逐个绘制到内存DC中的,在此期间窗体内容不会随着绘制进程的进展而变化,变化的是用户看不到的内存DC。因此会给用户死机的感觉。

      要避免这种情况的发生,就要尽量减少图形绘制的时间,一种方法是减少绘制工作量,即不需要重新绘制的图形部分直接拷贝到前台DC,只绘制需要更新的图形部分。但实际上,很多情况下无法确定哪些图形不需要绘制,哪些需要绘制。将前台DC划分为多个小区域内存DC进行拼接,可以逐个小DC进行绘制,这有点类似于GoogleMap中的图像显示。

      另一种方法是充分利用已显示的图形显示操作后的部分结果,待用户操作结束后再重新全部图形,例如,在图像的平移操作或地图漫游操作中,可以实时计算出当前已经显示图形在平移或漫游操作后的新位置,直接将其复制到pDC的新位置,用户拖拽或漫游操作结束后,再在内存DC中重新绘制移动后的所有图形,绘制完成后再复制到当前DC,由于新绘制的图像与原图像移动后有部分完全重合,因此不影响用户的观看结果。但在用户操作结束后同样要有一段时间的无响应。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值