MFC制作双缓冲无闪烁的字幕滚动条

最近一段时间由于项目需要,需要一个字幕滚动条,所以了解了一下双缓冲的绘图方法。

1.       闪烁产生原因

首先,介绍一下为什么会产生闪烁。我们在绘图时收到WM_PAINT消息后,系统会调用默认的画刷来填充被Invalidate 的区域,这样由于时间差的原因,会产生闪烁的现象。

2.       双缓冲原理

双缓冲使用内存缓冲区来解决由多重绘制操作造成的闪烁问题。当启用双缓冲时,所有绘制操作首先呈现到内存缓冲区,而不是屏幕上的绘图图面。所有绘制操作完成后,内存缓冲区直接复制到与其关联的绘图图面。因为在屏幕上只执行一个图形操作,所以消除了由复杂绘制操作造成的图像闪烁。
 

3. 相关的函数介绍

 

1)   为屏幕 DC 创建兼容的内存 DCCreateCompatibleDC()

if(!m_dcMemory.CreateCompatibleDC(NULL)) // CDC m_dcMemory;

{

    ::PostQuitMessage(0);

}

2)   创建位图CreateCompatibleBitmap()

m_Bmp.CreateCompatibleBitmap(&m_dcMemory, rt.Width(), rt.Height()); // CBitmap m_Bmp;

3)   把位图选入设备环境SelectObject()可以理解为选择画布

::SelectObject(m_dcMemory.GetSafeHdc(), m_Bmp);

4)   把绘制好的图形“拷贝“到屏幕上:BitBlt()

pdcView->BitBlt(0, 0, rt.Width(), rt.Height(), &m_dcMemory, 0, 0, SRCCOPY);

详细的函数可以查看MSDN

 

4. 本例中的实现

1)  OnTime的时候调用DrawHorizontalText方法

void CScrollMessageDlg::OnTimer(UINT nIDEvent)

{

// TODO: Add your message handler code here and/or call default

DrawHorizontalText();

CDialog::OnTimer(nIDEvent);

}

2)  双缓冲绘图

void CScrollMessageDlg::DrawHorizontalText()

{

 

       //若当前要显示的消息为空

       //清除显示区域

       if (!m_lsShowMessage.size())

       {

              Invalidate();//调用默认画刷m_Brush把整个区域涂黑

              return;

       }

 

       //计算当前滚动文字的文字

       if(m_StringCurrentPos < - (m_lsShowMessage[m_iShowCount].GetLength()* \

              m_logFont.lfWidth + m_logFont.lfWidth))

       {

              m_iShowCount = (++ m_iShowCount) % m_lsShowMessage.size();

              m_StringCurrentPos = m_SystemMetricsCX;  //回到起始位置

       }

       //判断是否暂停,若非,右距离减一

       if(!m_isPause)

              m_StringCurrentPos = m_StringCurrentPos - 1;  //每步向左移动距离

 

 

       //双缓冲绘图

       CRect rect;

       CDC *pDc; //屏幕绘图设备

       CDC memDC; //内存绘图设备

      

       GetClientRect(&rect);     

       pDc = this->GetDC();// 指针

       CBitmap memBitmap;

       //创建内存绘图设备

       memDC.CreateCompatibleDC(NULL);              

       memBitmap.CreateCompatibleBitmap(pDc,rect.right,rect.bottom);

       memDC.SelectObject(&memBitmap);

      

       //自定义绘图函数

      

       memDC.FillSolidRect(0,0,rect.Width(),rect.Height(),RGB(155,0,0));

       memDC.SelectObject(&m_font);

       memDC.SetTextColor(RGB (255,180,0));

       memDC.SetBkMode(TRANSPARENT);

      

       memDC.Rectangle(&rect);

       memDC.FillRect(&rect,&m_brush);

      memDC.TextOut(m_StringCurrentPos,m_iYLocation,m_lsShowMessage[m_iShowCount]);   

      

      

       //把内存绘图拷贝到屏幕

       pDc->BitBlt(rect.left,rect.top,rect.right,rect.bottom,&memDC,0,0,SRCCOPY);

             

       //清理释放

       this->ReleaseDC(pDc);

       memDC.DeleteDC();

       memBitmap.DeleteObject();

             

}

5. 总结

采用双缓冲的方法,可以极大的减少闪烁的现象,提高显示质量。关于JavaGDI+的双缓冲的方法,可以参考[url]http://zjyzjy.blog.51cto.com/329429/67374[/url] (Java) [url]http://zjyzjy.blog.51cto.com/329429/67370[/url] (GDI+)

关于具体的实现,可以参考本文的附件,同样推荐国外的牛人的多线程的实现方法。

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章