1. 闪烁产生原因
首先,介绍一下为什么会产生闪烁。我们在绘图时收到WM_PAINT消息后,系统会调用默认的画刷来填充被Invalidate 的区域,这样由于时间差的原因,会产生闪烁的现象。
2. 双缓冲原理
双缓冲使用内存缓冲区来解决由多重绘制操作造成的闪烁问题。当启用双缓冲时,所有绘制操作首先呈现到内存缓冲区,而不是屏幕上的绘图图面。所有绘制操作完成后,内存缓冲区直接复制到与其关联的绘图图面。因为在屏幕上只执行一个图形操作,所以消除了由复杂绘制操作造成的图像闪烁。
3. 相关的函数介绍
1) 为屏幕 DC 创建兼容的内存 DC:CreateCompatibleDC()
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.p,rect.right,rect.bottom,&memDC,0,0,SRCCOPY);
//清理释放
this->ReleaseDC(pDc);
memDC.DeleteDC();
memBitmap.DeleteObject();
}
5. 总结
采用双缓冲的方法,可以极大的减少闪烁的现象,提高显示质量。关于Java和GDI+的双缓冲的方法,可以参考[url]zjyzjy.blog.51cto/329429/67374[/url] (Java) [url]zjyzjy.blog.51cto/329429/67370[/url] (GDI+)。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论