Your Ad Here
首页 | 编程语言 | 网站建设 | 游戏天堂 | 冲浪宝典 | 网络安全 | 操作系统 | 软件时空 | 硬件指南 | 病毒相关 | IT 认证
软讯网络 > 编程语言 > Visual C++ > 双缓冲方法解决屏幕刷新闪烁的问题
【标  题】:双缓冲方法解决屏幕刷新闪烁的问题
【关键字】:方法,刷,冲,缓冲,屏幕,闪烁
【来  源】:网络

双缓冲方法解决屏幕刷新闪烁的问题

Your Ad Here

下载本文所附源代码

关键字
双缓冲
原作者姓名 戚高

介绍
在论坛中经常见到关于刷新时界面闪烁的帖子,如何控制在进行高效绘图时不出现界面闪烁的感觉呢,下文就双缓冲方法进行讲解.

正文
图形为什么会闪烁的原因是:我们的绘图过程大多放在OnDraw或者OnPaint函数中,OnDraw在进行屏幕显示时是由OnPaint进行调用的。当窗口由于任何原因需要重绘时,总是先用背景色将显示区清除,然后才调用OnPaint,而背景色往往与绘图内容反差很大,这样在短时间内背景色与显示图形的交替出现,使得显示窗口看起来在闪。如果将背景刷设置成NULL,这样无论怎样重绘图形都不会闪了。当然,这样做会使得窗口的显示乱成一团,因为重绘时没有背景色对原来绘制的图形进行清除,而又叠加上了新的图形。有的人会说,闪烁是因为绘图的速度太慢或者显示的图形太复杂造成的,其实这样说并不对,绘图的显示速度对闪烁的影响不是根本性的。
如何实现双缓冲:在OnDraw(CDC *pDC)中:
      CDC MemDC; //首先定义一个显示设备对象
      CBitmap MemBitmap;//定义一个位图对象

      //随后建立与屏幕显示兼容的内存显示设备
      MemDC.CreateCompatibleDC(NULL);
      //这时还不能绘图,因为没有地方画 ^_^
      //下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小
      MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight);
      //将位图选入到内存显示设备中
      //只有选入了位图的内存显示设备才有地方绘图,画到指定的位图上
      CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);
      //先用背景色将位图清除干净,这里我用的是白色作为背景
      //你也可以用自己应该用的颜色
      MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255));
      //绘图
      MemDC.MoveTo(……);
      MemDC.LineTo(……);

      //将内存中的图拷贝到屏幕上进行显示
      pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY);
      //绘图完成后的清理
      MemBitmap.DeleteObject();
      MemDC.DeleteDC();


以论坛的一个帖子例子为例来说明一些具体如何解决问题.
帖子那容是:

我想让一个区域动起来,
如何解决窗口刷新时区域的闪烁。
void CJhkljklView::OnDraw(CDC* pDC)
{
    CJhkljklDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    // TODO: add draw code for native data here
            int i;
    int x[20],y[20];
    CPen hPen;
     POINT w[5];
    
             x[0]=a/100+10;
             x[1]=a/100+30;
                 x[2]=a/100+80;
                 x[3]=a/100+30;
                 x[4]=a/100+10;

                     y[0]=10;
                  y[1]=10;
                   y[2]=25;
                    y[3]=40;
                     y[4]=40;    

      for (i=0;i<5;i++)
      {         w[i].x=x[i];
      w[i].y=y[i];
      }
      //CClientDC dc(this);
             //hPen=CreatePen(PS_SOLID,1,RGB(255,0,0));
      CRgn argn,Brgn;
        CBrush abrush(RGB(40,30,20));
        argn.CreatePolygonRgn(w, 5, 1);// point为CPoint数组,
        pDC->FillRgn(&argn, &abrush);
         abrush.DeleteObject();
}

void CJhkljklView::OnTimer(UINT nIDEvent)
{
    // TODO: Add your message handler code here and/or call default
        InvalidateRect(NULL,true);
        UpdateWindow();
        a+=100;
    CView::OnTimer(nIDEvent);
}

int CJhkljklView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if (CView::OnCreate(lpCreateStruct) == -1)
        return -1;
    
    // TODO: Add your specialized creation code here
    SetTimer(1,10,NULL);
    return 0;
}


利用定时器直接进行10毫秒的屏幕刷新,这样效果会出现不停的闪烁的情况.

解决方法利用双缓冲,首先触发WM_ERASEBKGND,然后修改返回TRUE;
定义变量:
CBitmap *m_pBitmapOldBackground ;
CBitmap m_bitmapBackground ;
CDC m_dcBackground;

//绘制背景
if(m_dcBackground.GetSafeHdc()== NULL|| (m_bitmapBackground.m_hObject == NULL))
    {
        m_dcBackground.CreateCompatibleDC(&dc);
        m_bitmapBackground.CreateCompatibleBitmap(&dc,rect.Width(),rect.Height()) ;
        m_pBitmapOldBackground = m_dcBackground.SelectObject(&m_bitmapBackground) ;
        //DrawMeterBackground(&m_dcBackground, rect);
        CBrush brushFill, *pBrushOld;        
        // 背景色黑色
        brushFill.DeleteObject();
        brushFill.CreateSolidBrush(RGB(255, 255, 255));
        pBrushOld = m_dcBackground.SelectObject(&brushFill);
        m_dcBackground.Rectangle(rect);
        m_dcBackground.SelectObject(pBrushOld);
    }
    memDC.BitBlt(0, 0, rect.Width(), rect.Height(),
                       &m_dcBackground, 0, 0, SRCCOPY) ;

    //绘制图形
    int i;
    int x[20],y[20];
    CPen hPen;
    POINT w[5];
    
    x[0]=a/100+10;
    x[1]=a/100+30;
    x[2]=a/100+80;
    x[3]=a/100+30;
    x[4]=a/100+10;
    
    y[0]=10;
    y[1]=10;
    y[2]=25;
    y[3]=40;
    y[4]=40;
    
    
    
    for (i=0;i<5;i++)
    {         w[i].x=x[i];
    w[i].y=y[i];
    }
    //CClientDC dc(this);
    //hPen=CreatePen(PS_SOLID,1,RGB(255,0,0));
    CRgn argn,Brgn;
    CBrush abrush(RGB(40,30,20));
    argn.CreatePolygonRgn(w, 5, 1);// point为CPoint数组,
    memDC.FillRgn(&argn, &abrush);
    abrush.DeleteObject();
}


这样编译运行程序就会出现屏幕不闪烁的情况了.

如果有什么问题请和我联系:13975102873@hnmcc.com

为什么要学Win32及Win32程序框架:【上一篇】
图形显示CPU内存利用率:【下一篇】
【相关文章】
  • VC++中进程与多进程管理的方法
  • 用VC 6.0实现串行通信的三种方法
  • 工业控制--串口通讯方法(WINAPI实现)
  • 检查和设置缓冲区
  • 远程设备使用高级寻址方法
  • Cisco的实现方法
  • 城域网MPLS VPN的几种实现方法
  • OSPF路由聚合的两种方法
  • 路由器测试的类型和方法
  • 中小企业部署VoIP讲方法
  • 【随机文章】
  • gets()函数实现数组录入时连续两次回车退出程序
  • 数据集处理技术文档_DataReader(DataAdapter)转换到DataSet的.NET技术(介绍一个已经写好的实用类)
  • 免杀asp木马三
  • [shell] nstf脚本
  • sendmail 支持大写用户名
  • 关于extern_C
  • 树行列表类及其应用
  • getopt()函数介绍
  • 中文拨号上网计时计费器 V4.12注册算法分析(2)
  • 杏林同学录(四)
  • 【相关评论】
    没有相关评论
    【发表评论】
    姓名:
    邮件:
    随机码*
    评论*
          
    |  首 页  |  版权声明  |  联系我们   |  网站地图  |
    CopyRight © 2004-2007 bbb软讯网络 All Rigths Reserved.