CListView是那样简单好用,以至于咱们爱它就好像老鼠爱大米一样。可是你是否知道它的控制类CListCtrl有很多雷区呢?尤其当Items非常大时(5000以上),对CListCtrl的用法不当,会导致CListView的加载明显延迟。来看看下面载入逗号分隔文本CSV的常见用法:
//Created By RAINEE,2006-3-8
void CRecordDoc::LoadFileCSV(CStdioFile& file_Open,
CListCtrl& openListCtrl, int& ReadNum)
{
ReadNum = 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%
//Created By RAINEE,2006-3-8
void CRecordDoc::LoadFileCSV(CStdioFile& file_Open,
CListCtrl& openListCtrl, int& ReadNum)
{
SetCursor(LoadCursor(NULL, IDC_WAIT));
openListCtrl.SetRedraw(FALSE);
ReadNum = 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%
//Created By RAINEE,2006-3-8
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));
}