环境:SDI程序,View的基类是CListView.显示方式是Report,不使用Grid网格样式
ListView里只有2列
1.在View中设置一个定时器,每10毫秒或者50毫秒插入项,插入的位置是0,最上面
2.在没有网格的情况下,CListView会闪烁,原因在于显示2列的区域会先被擦除为背景色,然后再写项,通过重写OnEraseBackground,时之在填充背景色的时候只填充Client区域排除2列所占区域的区域,而不对2列所占区域进行重绘。解决了
第二条的闪烁问题,使用SetRedraw是不能解决的。请注意这一点3。增加listview的网格样式,出现闪烁,表格线在闪烁。此时的闪烁与第二条无关,即使OnEraseBackground改为return TRUE也不能消除,说明与擦除背景无关
于是,重写OnPaint,不使用网格样式,而是通过绘图方式,首先使用默认的基类OnPaint,把项的文字部分显示,然后开始绘制表格,只绘制在当前可视的范围。此方法属于自画表格。但是问题依旧。再次更改,使用双缓冲绘制,先在memdc中绘制好表格,然后把该memdc与clientdc的相对应区域(此时该区域的文字绘制已经由基类的OnPain完成)进行SRCPAINT进行处理,实现两个DC叠加,
但是仍然会有一定闪烁。欢迎高手参与讨论或者帮忙提出解决方案,再次感谢。
也请贴网址的高手注意,该问题的目的是解决自画表格线的情况下频繁在顶端插入数据时的闪烁,或者是使用grid样式时,频繁插入数据导致闪烁。如果贴出的网址代码,确实包含了该问题的解决,就最好。也请大家说两句。让我们这些初学者多学习学习
ListView里只有2列
1.在View中设置一个定时器,每10毫秒或者50毫秒插入项,插入的位置是0,最上面
2.在没有网格的情况下,CListView会闪烁,原因在于显示2列的区域会先被擦除为背景色,然后再写项,通过重写OnEraseBackground,时之在填充背景色的时候只填充Client区域排除2列所占区域的区域,而不对2列所占区域进行重绘。解决了
第二条的闪烁问题,使用SetRedraw是不能解决的。请注意这一点3。增加listview的网格样式,出现闪烁,表格线在闪烁。此时的闪烁与第二条无关,即使OnEraseBackground改为return TRUE也不能消除,说明与擦除背景无关
于是,重写OnPaint,不使用网格样式,而是通过绘图方式,首先使用默认的基类OnPaint,把项的文字部分显示,然后开始绘制表格,只绘制在当前可视的范围。此方法属于自画表格。但是问题依旧。再次更改,使用双缓冲绘制,先在memdc中绘制好表格,然后把该memdc与clientdc的相对应区域(此时该区域的文字绘制已经由基类的OnPain完成)进行SRCPAINT进行处理,实现两个DC叠加,
但是仍然会有一定闪烁。欢迎高手参与讨论或者帮忙提出解决方案,再次感谢。
也请贴网址的高手注意,该问题的目的是解决自画表格线的情况下频繁在顶端插入数据时的闪烁,或者是使用grid样式时,频繁插入数据导致闪烁。如果贴出的网址代码,确实包含了该问题的解决,就最好。也请大家说两句。让我们这些初学者多学习学习
而我的需求则侧重这一点,相信大多数作通信开发或者数据库开发的朋友应该都知道使用CListView和CEdit显示实时数据时的问题。
抛砖引玉,希望能有启发式的想法能够看到
------------------------------------------------------------------------------------你的意思是我在绘制表格的时候,原先的有表格的地方要擦除掉?这个问题我要测试一下。此外customdraw的处理,我大概测试了一下,发现当列表框开始滚动的时候,pLVCD->nmcd.dwDrawStage这个始终是1,也就是CDDS_PREPAINT此时绘制表格的时机还要继续捉摸
我这里用timer是为了模拟如果是通信服务端,显示数据传输的时候,子线程通过Post消息方式来显示信息。通信的频繁的时候,肯定要少于一秒的。使用timer的目的仅仅是为了模拟快速插入项的这种情况
2。此时我再画网格线的时候是正常的,但由于item的文字部分的背景色并非是透明的,在下一个绘制的时候,这个item的背景色遮盖了原先的网格线,其后再次绘制网格线,交替作用下,网格线的闪烁产生了,此时文字和文字背景没有产生闪烁。由于listview的WM_ERASEBKGND消息我已经处理过了。但每个item的文字背景却不受此影响,依然会再绘制的时候覆盖上次画上的网格线。问题的关键在于如何处理item的文字背景时之比其所在rect要小一些,不会覆盖网格线,或者是item的文字背景想办法处理成透明的。明天再试试,可否解决
void CxxxView::OnInitialUpdate()
{
...
if (m_pdcMemory->GetSafeHdc() == NULL) {
CClientDC dc(this);
OnPrepareDC(&dc);
... m_pdcMemory->CreateCompatibleDC(&dc);
// makes bitmap same size as display window
m_pBitmap->CreateCompatibleBitmap(&dc, rectMax.right,
rectMax.bottom);
}
}
void CxxxView::OnPaint()
{
CPaintDC dc(this); // device context for painting
OnPrepareDC(&dc);
CRect rectUpdate;
dc.GetClipBox(&rectUpdate);
CBitmap* pOldBitmap = m_pdcMemory->SelectObject(m_pBitmap);
m_pdcMemory->SelectClipRgn(NULL);
m_pdcMemory->IntersectClipRect(&rectUpdate);
CBrush backgroundBrush((COLORREF) ::GetSysColor(COLOR_WINDOW));
CBrush* pOldBrush = m_pdcMemory->SelectObject(&backgroundBrush);
m_pdcMemory->PatBlt(rectUpdate.left, rectUpdate.top,
rectUpdate.Width(), rectUpdate.Height(),
PATCOPY);
OnDraw(m_pdcMemory);
dc.BitBlt(rectUpdate.left, rectUpdate.top,
rectUpdate.Width(), rectUpdate.Height(),
m_pdcMemory, rectUpdate.left, rectUpdate.top,
SRCCOPY);
m_pdcMemory->SelectObject(pOldBitmap);
m_pdcMemory->SelectObject(pOldBrush);
}