• 双缓冲绘图


    【问题】在以前的双缓冲Demo中,发现这个在移动一张牌的时候,效率还能忍受过去。但是当应用双缓冲技术到显示多张纸牌的时候,我们会发现效率已经不能再让人忍受了。移动纸牌发生飘移;发牌的时候,当把定时器间隔修改为1ms的时候,速度还是很慢。为此需要对双缓冲的效率进行改善。 【改善措施】经过调查,改善的措施具体如下:

     1. 将创建内存画布的工作移动到OnSize函数中去做,也就是当窗口大小发生变化的时候,才能去再次创建内存画布,否则就用原来已经创建好的。 void CDemoDlg::OnSize(UINT nType, int cx, int cy) { CDialog::OnSize(nType, cx, cy); // TODO: Add your message handler code here CClientDC clientDC(this); CreateMemoryCanvas(&clientDC); } 2. InvalidateRect这个函数在使用的时候,要指定刷新区域。因为计算机的绘图效率很高,但是显示效率却很低。在OnPaint函数中去判断是否与指定的刷新区域相交,如果相交,则进行绘图显示,否则不去显示。这样做极大地提高了刷新效率。 void CDemoDlg::OnPaint() { CPaintDC dc(this); // device context for painting dc.GetClipBox(m_clipRect); CRect intersectRect; // 将背景图片显示在内存DC中 int nDestX = 0; int nDestY = 0; CRect bkRect; for (nDestY = 0; nDestY <= m_clientRect.bottom /*- BK_WIDTH*/; nDestY +=BK_WIDTH) { for (nDestX = 0; nDestX <= m_clientRect.right /*- BK_WIDTH*/; nDestX += BK_WIDTH) { bkRect.left = nDestX; bkRect.top = nDestY; bkRect.right = nDestX + BK_WIDTH; bkRect.bottom = nDestY + BK_WIDTH; // 如果当前区域与指定刷新区域相交,则进行绘图显示。 if (intersectRect.IntersectRect(bkRect, m_clipRect)) { DisplayBmp(&dc, &m_memDC, IDB_BITMAP6, nDestX, nDestY); } } } // 把纸牌2显示在内存DC中。 if (intersectRect.IntersectRect(m_rectBmp2, m_clipRect)) { DisplayBmp(&dc, &m_memDC, IDB_BITMAP2, m_rectBmp2.left, m_rectBmp2.top); } // 把纸牌1显示在内存DC中。 if (intersectRect.IntersectRect(m_rectBmp1, m_clipRect)) { DisplayBmp(&dc, &m_memDC, IDB_BITMAP1, m_rectBmp1.left, m_rectBmp1.top); } // 将内存DC上的图象拷贝到前台 dc.BitBlt(0, 0, m_clientRect.Width(), m_clientRect.Height(), &m_memDC, 0, 0, SRCCOPY); } void CDemoDlg::OnMouseMove(UINT nFlags, CPoint point) { // TODO: Add your message handler code here and/or call default // 如果可以移动,则更新当前纸牌矩形区域 if (m_bRemove) { // 更新当前纸牌矩形区域 CRect oldRect = m_rectBmp1; m_rectBmp1.left = m_rectBmp1.left + (point.x - m_ptOld.x); m_rectBmp1.top = m_rectBmp1.top + (point.y - m_ptOld.y); m_rectBmp1.bottom = m_rectBmp1.top + CARD_HEIGHT; m_rectBmp1.right = m_rectBmp1.left + CARD_WIDTH; CRect newRect = m_rectBmp1; // 这里为了擦除移牌的痕迹,刷新的区域 = 该纸牌的旧矩形区域 + 该纸牌的新矩形区域。 m_paintRect.UnionRect(oldRect, newRect); InvalidateRect(m_paintRect, FALSE); // 记录当前坐标,为旧的坐标 m_ptOld = point; } CDialog::OnMouseMove(nFlags, point); } 【改善效果】:在以前移动一张纸牌,刷新所需要的时间大概为47ms.(这里要画104张纸牌)。 通过以上的改善措施后,刷新所需要的时间不到1ms(这里只画一张纸牌)。

  • 相关阅读:
    EditPlus使用技巧
    PL/SQL Dev的问题
    解决httpModules 未能从程序集 XX 加载类型 XXX 的错误
    IE浏览器无法显示背景,字体显示很大问题的解决办法[转]
    如何在Outlook2003中加入农历节气
    再谈Oracle在Windows下的权限问题
    Vista下安装布署注册的问题解决
    [转]关于管理的经典故事(员工激励)
    开始应用AJAX
    Aptana IDE 中文乱码的问题解决
  • 原文地址:https://www.cnblogs.com/buffer/p/1407359.html
Copyright © 2020-2023  润新知