VC驿站

 找回密码
 加入驿站

QQ登录

只需一步,快速开始

搜索
查看: 1723|回复: 4

[交流] CListCtrl 防止闪烁

[复制链接]
49_avatar_middle
在线会员 发表于 2016-5-14 00:41:26 | 显示全部楼层 |阅读模式
一:
彻底解决了CListCtrl的闪烁问题.此灵感来自于WindowMediaPlayer SDK 9
方法很简单.如下:
在对话框上加了个静态文本框.并把文本框的样式设为透明.再
用SetParent()函数把CListCtrl的父窗口设为刚加的静态文本框.嘿嘿彻底不闪了...
代码如下:
1在CMyDlg中添加成员  CListCtrl   m_List;
2
BOOL CMyi5Dlg::OnInitDialog()
{

         1.RECT rcRect;
2.CWnd* pParent=GetDlgItem(IDC_STATIC_PARENT);
3.pParent->GetWindowRect (&rcRect);
4.pParent->ScreenToClient(&rcRect);
5.m_List.Create (WS_VISIBLE|WS_BORDER,rcRect,this, 50);
6.m_List.SetParent(pParent);
}  // 以上代码去除CListCtrl闪烁问题


而它原来的父窗口还能处理它的各种事件. 比如 单击,双击事件:(动态创建需手动加消息映射表)

(第5句改成 m_List.Create(WS_VISIBLE|WS_BORDER,rcRect,pParent, 50);第6句不要了)
那么对话框就无法接收和处理到CListCtrl的消息了.这是怎么会事?)

回答:有些控件只认创建时的父窗口,一些通知消息只发给这个创建时的父窗口,不会发给之后SetParent设置的父窗口,象ListView,ToolBar这类控件就是,你创建时设置父窗口为STATIC,这些通知消息就发给STATIC了,而STATIC没有消息转发机制,因此对话框就收不到这些消息了。




二:
防止CListCtrl闪烁的几种方法 (2009-12-28 11:24:15)转载▼
标签: listctrl 闪烁 防止 it        分类: VC及相关
1.使用SetRedraw禁止窗口重绘,操作完成后,再恢复窗口重绘
m_ctlList.SetRedraw(FALSE);
//以下为更新数据操作
//……
//恢复窗口重绘
m_ctlList.SetRedraw(TRUE);
2.使用LockWindowUpdate禁止窗口重绘,操作完成后,用UnlockWindowUpdate恢复窗口重绘
m_ctlList.LockWindowUpdate();
//以下为更新数据操作
//……
//恢复窗口重绘
m_ctlList.UnlockWindowUpdate();
3.使用ListCtrl的内部双缓冲
m_ctlLisit.SetExtendedStyle(m_ctlLisit.GetExtendedStyle()|LVS_EX_DOUBLEBUFFER);
VC6未定义LVS_EX_DOUBLEBUFFER宏,使用者可以自定义,如下:
#define LVS_EX_DOUBLEBUFFER 0x00010000
4.Virtual List
首先要设置ListCtrl风格为LVS_REPORT | LVS_OWNERDATA或在ListCtrl属里中的More Styles页面中选中Owner data复选框。
其次要向应LVN_GETDISPINFO消息;
void OnGetdispinfoList(NMHDR* pNMHDR, LRESULT* pResult)
{
LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;
LV_ITEM *pItem = &(pDispInfo)->item;
char szText[128] = {0};
if (pItem->mask & LVIF_TEXT)
{
//使缓冲区数据与表格子项对应
//m_ArrayBuff为二维数组
//定义如下 int m_ArrayBuff[2048][4];
  _stprintf(szText,_T("%d"),m_ArrayBuff[pItem->iItem][pItem->iSubItem]);   
  pItem->pszText = szText;  
}
*pResult = 0;
}
最后便是生成缓冲区数据
void Insertdata()
{
//删除之前的数据
m_ctlList.SetItemCountEx(0);
m_ctlList.Invalidate();
    m_ctlList.UpdateWindow();
srand( (unsigned)time( NULL ));

//生成新的数据缓冲区
int nItemCount = 2048;
for (int i = 0;i < nItemCount; i ++)
{
  for (int k = 0;k < 4;k ++)
  {
   m_ArrayBuff[i][k] = rand()%2048 + 1;
  }
}
if (nItemCount < 2)   
  m_ctlList.SetItemCountEx(1);   
else
  m_ctlList.SetItemCountEx(nItemCount);
m_ctlList.Invalidate();
}
若要修改数据,只要修改缓冲区m_ArrayBuff的数据即可以
5.Custom Redraw
既然是自绘,首先当然是重载CListCtrl类,并接管WM_ERASEBKGND消息,去掉默认的处理,改为不处理
BOOL CListCtrlEx::OnEraseBkgnd(CDC* pDC)
{
//响应WM_ERASEBKGND消息
return false;
//屏蔽默认处理
//return CListCtrl::OnEraseBkgnd(pDC);
}
void CListCtrlEx::OnPaint()
{
    //响应WM_PAINT消息
    CPaintDC dc(this); // device context for painting
    CRect rect;
    CRect headerRect;
    CDC MenDC;//内存ID表  
    CBitmap MemMap;
    GetClientRect(&rect);   
    GetDlgItem(0)->GetWindowRect(&headerRect);  
    MenDC.CreateCompatibleDC(&dc);  
    MemMap.CreateCompatibleBitmap(&dc,rect.Width(),rect.Height());
    MenDC.SelectObject(&MemMap);
    MenDC.FillSolidRect(&rect,RGB(228,236,243));  
    //这一句是调用默认的OnPaint(),把图形画在内存DC表上  
    DefWindowProc(WM_PAINT,(WPARAM)MenDC.m_hDC,(LPARAM)0);      
    //输出  
    dc.BitBlt(0,headerRect.Height(),rect.Width(),  rect.Height(),&MenDC,0, headerRect.Height(),SRCCOPY);  
    MenDC.DeleteDC();
    MemMap.DeleteObject();
}


5也可以重写一个类继承CListCtrl, 然后添加消息WM_ERASEBKGND, 在该类中会自动生成方法OnEraseBkgnd(), 在该方法中将默认的“return CListCtrl::OnEraseBkgnd(pDC);”改为“return FALSE”即可

原因是每次刷新CListCtrl控件时,其背景也被刷新了,那么我们设置其背景不再刷新即可




上一篇:为什么在vc上一运行不起来,有没有大神帮我看看
下一篇:基于opencv实现的一个摄像头模块
40_avatar_middle
在线会员 发表于 2016-5-14 11:57:01 | 显示全部楼层
多谢分享
49_avatar_middle
ico_lz  楼主| 发表于 2016-5-14 13:59:51 | 显示全部楼层
void CMyListCtrl::OnPaint()
{
        CPaintDC dc(this); // device context for painting
        // TODO:  在此处添加消息处理程序代码
        // 不为绘图消息调用
        //CListCtrl::OnPaint();

          CRect rcClient, rcClip, rcHeader;
          GetClientRect(&rcClient);
  
          GetHeaderCtrl()->GetWindowRect(&rcHeader);
          dc.GetClipBox(&rcClip);
  
          CDC MemDC;
          CBitmap MemBitmap, *pOldBitmap;
  
          MemDC.CreateCompatibleDC(&dc);
          int nMode = MemDC.SetMapMode(dc.GetMapMode());
  
          MemBitmap.CreateCompatibleBitmap(&dc, rcClient.Width(), rcClient.Height());
          pOldBitmap = MemDC.SelectObject(&MemBitmap);
          MemDC.FillSolidRect(&rcClient, GetBkColor());
  
          CRgn rgn;
          rgn.CreateRectRgn(rcClip.left, rcClip.top, rcClip.right, rcClip.bottom);
          MemDC.SelectClipRgn(&rgn);
          DefWindowProc(WM_PAINT, (WPARAM)MemDC.m_hDC, (LPARAM)0);
          MemDC.SelectClipRgn(NULL);
  
          if (rcClip.top < rcHeader.Height())
                  rcClip.top = rcHeader.Height();
  
          dc.BitBlt(rcClip.left, rcClip.top, rcClip.Width(), rcClip.Height(), &MemDC, rcClip.left, rcClip.top, SRCCOPY);
  
          MemDC.SetMapMode(nMode);
          MemDC.SelectObject(pOldBitmap);
          MemDC.DeleteDC();
          MemBitmap.DeleteObject();
          rgn.DeleteObject();
}
48_avatar_middle
在线会员 发表于 2018-5-8 10:12:04 | 显示全部楼层
使用双缓冲后,拖动滚动条的时候,反应很慢
15_avatar_middle
在线会员 发表于 2018-5-12 21:04:44 | 显示全部楼层
的点点滴滴多多多多多多多多多多多
您需要登录后才可以回帖 登录 | 加入驿站 qq_login

本版积分规则

关闭

站长提醒上一条 /2 下一条

QQ|小黑屋|手机版|VC驿站 ( 辽ICP备09019393号tongdun|网站地图wx_jqr

GMT+8, 2019-5-23 20:05

Powered by Discuz! X3.4

© 2009-2019 cctry.com

快速回复 返回顶部 返回列表