我从 CMFCListControl 子类化并在报表视图 (LVS_REPORT) 中创建一个列表控件来显示数据。由于我的数据包含一百万条记录,因此填充列表控件的 AF 前期速度很慢(平均 6 分钟),但之后非常流畅。我使用 LVS_OWNERDATA 窗口样式切换到虚拟列表控件。它工作得更好(调试时为 75 秒),但是,在初始显示之后,任何滚动尝试都非常缓慢。它可以工作,并且永远不会崩溃,但需要 2 分钟才能显示更改。读取的数据在内存中的 std::map 中,因此磁盘驱动器或网络延迟问题不是原因。
void CAlbumListCtrl::OnLvnGetdispinfo(NMHDR *pNMHDR, LRESULT *pResult)
{
NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
LVITEM &Item = (pDispInfo)->item;
CString csTemp;
ASSERT(m_pLibrary);
if (!m_pLibrary)
AfxThrowMemoryException();
const CImageEntry *pEntry = m_pLibrary->GetImageEntryAt((size_t)Item.iItem);
//pListCtrl->SetItemText(nCount, 1, pEntry->GetItemName().c_str());
//pListCtrl->SetItemText(nCount, 2, pEntry->GetPathName().c_str());
//pListCtrl->SetItemText(nCount, 3, pLib->GetImageEntryType(pEntry).c_str());
if (Item.mask & LVIF_TEXT) //valid text buffer?
{
switch (Item.iSubItem)
{
case 0: //fill in ID
//_tcscpy_s(Item.pszText, Item.cchTextMax,
// m_Items[iItem].m_strItemText);
csTemp.Format(_T("%ld"), pEntry->GetItemId());
_tcscpy_s(Item.pszText, Item.cchTextMax, csTemp);
break;
case 1: //fill in sub item 1 text
_tcscpy_s(Item.pszText, Item.cchTextMax, pEntry->GetItemName().c_str());
break;
case 2: //fill in sub item 2 text
_tcscpy_s(Item.pszText, Item.cchTextMax, pEntry->GetPathName().c_str());
break;
case 3: //fill in sub item 1 text
_tcscpy_s(Item.pszText, Item.cchTextMax, m_pLibrary->GetImageEntryType(pEntry).c_str());
break;
//case 2: //fill in sub item 2 text
// _tcscpy_s(Item.pszText, Item.cchTextMax, pEntry->GetPathName().c_str());
// break;
default:
break;
}
}
*pResult = 0;
}
int CAlbumView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
m_wndTabCtrl.Create(TCS_TABS | TCS_FIXEDWIDTH | WS_CHILD | WS_VISIBLE,
CRect(0, 0, 20, 20), this, IDC_ALBUMVIEW_HEADERTAB);
if (!m_wndTabCtrl.m_hWnd)
return -1;
m_wndTabCtrl.InsertItem(0, _T("List View"));
m_wndTabCtrl.InsertItem(1, _T("Tree View"));
m_listCtrl.Create(LVS_REPORT | LVS_SHOWSELALWAYS | LVS_OWNERDATA | WS_VISIBLE, CRect(0, 0, 20, 20), this, IDC_LISTCTRL);
m_listCtrl.SetExtendedStyle(LVS_EX_FULLROWSELECT | LVS_EX_DOUBLEBUFFER | LVS_EX_ONECLICKACTIVATE);
m_listCtrl.InsertColumn(0, _T("ID"), LVCFMT_CENTER, 150);
m_listCtrl.InsertColumn(1, _T("Nickname"), LVCFMT_CENTER, 100);
m_listCtrl.InsertColumn(2, _T("Image File Pathname"), LVCFMT_CENTER, 500);
m_listCtrl.InsertColumn(3, _T("Image Type"), LVCFMT_CENTER, 100);
m_listCtrl.InsertColumn(4, _T("Dimensions"), LVCFMT_CENTER, 75);
m_listCtrl.InsertColumn(5, _T("Color Depth"), LVCFMT_CENTER, 95);
m_listCtrl.InsertColumn(6, _T("Tags"), LVCFMT_CENTER, 150);
m_treeCtrl.Create(TVS_HASBUTTONS | WS_VISIBLE, CRect(0, 0, 20, 20), this, IDC_TREECTRL);
SetVisibleViewCtrl(0);
return 0;
}
void CAlbumView::UpdateView()
{
std::map<wstring, vector<wstring>> mapImageFilesByFolder;
time_t start = time(NULL);
auto *pFrame = GetParentFrame();
size_t nCount = 0;
if (pFrame)
{
CImageLibrary *pLib = pFrame->GetImageLibrary();
CAlbumView *pView = pFrame->GetAlbumView();
CAlbumListCtrl *pListCtrl = pView->GetListCtrl();
CAlbumTreeCtrl *pTreeCtrl = pView->GetTreeCtrl();
CUpdatingViewDlg dlg;
dlg.Create(this);
dlg.ShowWindow(SW_SHOW);
dlg.CenterWindow();
dlg.RedrawWindow();
pListCtrl->SendMessage(WM_SETREDRAW, FALSE);
pTreeCtrl->SendMessage(WM_SETREDRAW, FALSE);
nCount = pLib->GetImageCount();
pListCtrl->SetItemCountEx((int)nCount);
pListCtrl->SetImageLibrary(pLib);
SetThreadPriority(GetCurrentThread(), 7);
POSITION pos = pLib->EnumImageEntries();
if (::IsWindow(pListCtrl->m_hWnd))
{
pListCtrl->DeleteAllItems();
pTreeCtrl->DeleteAllItems();
int nCount = 0;
while (pos != (POSITION)-1)
{
CString csTemp;
const CImageEntry *pEntry = pLib->GetCurrentImageEntry(pos);
csTemp.Format(_T("%ld"), pEntry->GetItemId());
pListCtrl->InsertItem(nCount, csTemp);
//pListCtrl->SetItemText(nCount, 1, pEntry->GetItemName().c_str());
//pListCtrl->SetItemText(nCount, 2, pEntry->GetPathName().c_str());
//pListCtrl->SetItemText(nCount, 3, pLib->GetImageEntryType(pEntry).c_str());
//pTreeCtrl->ParseAndAddFile(pEntry->GetPathName().c_str());
pos = pLib->GetNextPos(pos);
++nCount;
}
CString csTemp;
csTemp.Format(_T("Done in %d seconds."), time(NULL) - start);
MessageBox(csTemp, _T("X"));
SetThreadPriority(GetCurrentThread(), 0);
pListCtrl->SendMessage(WM_SETREDRAW, TRUE);
pListCtrl->RedrawWindow(NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
pTreeCtrl->SendMessage(WM_SETREDRAW, TRUE);
pTreeCtrl->RedrawWindow(NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
dlg.ShowWindow(SW_HIDE);
dlg.DestroyWindow();
}
}
}