zoukankan      html  css  js  c++  java
  • CListCtrl用法!

    CListView是那样简单好用,以至于咱们爱它就好像老鼠爱大米一样。可是你是否知道它的控制类CListCtrl有很多雷区呢?尤其当 Items非常大时(5000以上),对CListCtrl的用法不当,会导致CListView的加载明显延迟。来看看下面载入逗号分隔文本CSV的常见用法:


    --------------------------------------------------------------------------------

    void CRecordDoc::LoadFileCSV(CStdioFile& file_Open,
                                                      CListCtrl& openListCtrl, int& ReadNum)
    {

           ReadNum = 0;
          
           int nSubItem = 0;
           int nStart = 0, nEnd = 0;
           CString strTempOpen;
           const TCHAR tcSplit = _T(',');
           while(1)
           {
                  if(file_Open.ReadString(strTempOpen)==FALSE) break;
                 
                  for (nSubItem = nStart = 0; nSubItem < 11; nSubItem++)
                  {
                         nEnd = strTempOpen.Find(tcSplit, nStart);
                         if (nEnd == -1)
                         {
                                break;
                         }
     
                         if (nSubItem == 0)
                         {
                                ReadNum ++;
                                openListCtrl.InsertItem(0, strTempOpen.Mid(nStart, nEnd - nStart));
                         }
                         else
                         {
                                openListCtrl.SetItemText(0, nSubItem, strTempOpen.Mid(nStart, nEnd - nStart));
                         }
     
                         nStart = nEnd + 1;
                  }
           };
     }

    --------------------------------------------------------------------------------

    看出问题了么?

    优化1:巧用CListCtrl::SetRedraw(BOOL bRedraw)函数,性能提升75%


    --------------------------------------------------------------------------------

    void CRecordDoc::LoadFileCSV(CStdioFile& file_Open,
                                                      CListCtrl& openListCtrl, int& ReadNum)
    {
           SetCursor(LoadCursor(NULL, IDC_WAIT));
           openListCtrl.SetRedraw(FALSE);
          
           ReadNum = 0;
          
          int nSubItem = 0;
           int nStart = 0, nEnd = 0;
           CString strTempOpen;
           const TCHAR tcSplit = _T(',');
           while(1)
           {
                  if(file_Open.ReadString(strTempOpen)==FALSE) break;
                 
                  for (nSubItem = nStart = 0; nSubItem < 11; nSubItem++)
                  {
                         nEnd = strTempOpen.Find(tcSplit, nStart);
                         if (nEnd == -1)
                         {
                                break;
                         }
     
                         if (nSubItem == 0)
                         {
                                ReadNum ++;
                                openListCtrl.InsertItem(0, strTempOpen.Mid(nStart, nEnd - nStart));
                         }
                         else
                         {
                                openListCtrl.SetItemText(0, nSubItem, strTempOpen.Mid(nStart, nEnd - nStart));
                         }
     
                         nStart = nEnd + 1;
                  }
           };
          
           openListCtrl.SetRedraw(TRUE);
           SetCursor(LoadCursor(NULL, IDC_ARROW));
    }

    --------------------------------------------------------------------------------

    不卖关子了,接着来

    优化2:新纪录项追加在List底部,性能提高35%


    --------------------------------------------------------------------------------

    void CRecordDoc::LoadFileCSV(CStdioFile& file_Open,
                                                      CListCtrl& openListCtrl, int& ReadNum)
    {
           SetCursor(LoadCursor(NULL, IDC_WAIT));
           openListCtrl.SetRedraw(FALSE);
          
            ReadNum = 0;
          
           int nSubItem = 0;
           int nRootItem = -1;//插入项
           int nStart = 0, nEnd = 0;
           CString strTempOpen;
           const TCHAR tcSplit = _T(',');
           while(1)
           {
                  if(file_Open.ReadString(strTempOpen)==FALSE) break;
                 
                  for (nSubItem = nStart = 0; nSubItem < 11; nSubItem++)
                  {
                         nEnd = strTempOpen.Find(tcSplit, nStart);
                         if (nEnd == -1)
                         {
                                break;
                         }
     
                         if (nSubItem == 0)
                         {
                                nRootItem ++;
                                openListCtrl.InsertItem(nRootItem, strTempOpen.Mid(nStart, nEnd - nStart));
                         }
                         else
                         {
                                openListCtrl.SetItemText(nRootItem, nSubItem, strTempOpen.Mid(nStart, nEnd - nStart));
                         }
     
                         nStart = nEnd + 1;
                  }
           };
           ReadNum = nRootItem + 1;
          
           openListCtrl.SetRedraw(TRUE);
           SetCursor(LoadCursor(NULL, IDC_ARROW));
    }
    //优化3:删除某些选择行的数据,从后往前删,并且删之前把进度条置顶,并关刷新,性能提升80%


    --------------------------------------------------------------------------------
     
    void CRecordDoc::DeleteCSV(CListCtrl& openListCtrl)
    {
     
            SetCursor(LoadCursor(NULL, IDC_WAIT));
            openListCtrl.SetRedraw(FALSE);
            ::SendMessage(openListCtrl.m_hWnd, WM_VSCROLL, SB_TOP, 0);
          
           DWORD dwNum = openListCtrl.GetItemCount();
            for (int i = dwNum - 1; i > 0; i--)
           {
                  if(openListCtrl.GetCheck(i))
                          openListCtrl.DeleteItem(i);
           }
           //或者这里是openListCtrl.DeleteAllItems();
           openListCtrl.SetRedraw(TRUE);
           SetCursor(LoadCursor(NULL, IDC_ARROW));
    }

    --------------------------------------------------------------------------------
     如何解决CListCtrl的数据更新时候的闪烁问题
    方案1:窗口锁定技术。
    m_list.LockWindowUpdate()
    while()
      {
        //取出数据,插入到数据库中。
    }
    m_list.UnlockWindowUpdate()
    程序在每次循环的时候不闪烁了,但是每个查询周期还是闪烁。
    方案2:   不知道是否用对,每个查询周期还是要闪烁一次
    SetWindowRedraw(hwnd,   FALSE);
        //过程同上
    SetWindowRedraw(hwnd,   TRUE);
    方案3:虚拟列表技术
      codePrject上下载的例子是针对一次插入大容量数据时候的不闪烁技术。更改以后,
    每个周期改变数组的值,达到了要求。还是存在一些问题:
    (1)虚拟列表技术必须要CListCtrl控件设置成自绘。原来的一个类用来设置每行的背景
            颜色,不能用了。是在CodePrject上下载了一个CListCtrl例子,类CReportCtrl例子,
            二者不能融合。调试时候发现是OnCustomdrawMyList   ()函数中错误?
              它使用了消息反射技术,如函数
              OnCustomdrawMyList   (   NMHDR*   pNMHDR,   LRESULT*   pResult   ),不知道和虚拟列表
            技术使用的LVN_GETDISPINFO消息(对应函数OnGetdispinfoList(NMHDR*   pNMHDR,     
              LRESULT*   pResult))二者是怎么样的对应关系?

  • 相关阅读:
    MFC project for a non-Unicode character set is deprecated
    关于Visual Studio 2013 编译 multi-byte character set MFC程序出现 MSB8031 错误的解决办法
    字符串比较自实现
    各种语言里获取当前模块的方法:ABAP,ABSL,C,nodejs
    SAP CRM product attachment的document template功能
    ABAP, UI5和webpack的处理入口
    ABAP, Maven, CF App和Webpack的build
    json格式的字符串序列化和反序列化的一些高级用法
    SAP ABAP Netweaver容器化, 不可能完成的任务吗?
    UI Component in CRM WebUI and Hybris
  • 原文地址:https://www.cnblogs.com/liyanwei/p/2002960.html
Copyright © 2011-2022 走看看