防止CListCtrl 闪烁的几种方法

一:
彻底解决了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控件时,其背景也被刷新了,那么我们设置其背景不再刷新即可
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值