Raspuns: o lista virtuala rezolva problema.
Pe scurt, o lista virtuala este un control listview care are setat stilul LVS_OWNERDATA. Aceasta nu mai trebuie sa tina intern informatiile pentru fiecare item ci doar, de fiecare data cand are nevoie (un item devine vizibil si trebuie afisat), cere aceste informatii ferestrei parinte trimitandu-i mesajul de notificare LVN_GETDISPINFO (via WM_NOTIFY).
Ceea ce avem de facut este:
- Setam stilul LVS_OWNERDATA.
- Setam numarul de item-uri cu CListCtrl::SetItemCountEx.
- Handluim LVN_GETDISPINFO pentru a-i da listei informatiile necesare.
Mai jos este un exemplu simplificat de lista virtuala implementata intr-o clasa derivata din CListView (MFC).
Exemplu
Cod: |
// Override CListView::PreCreateWindow // LVS_OWNERDATA style makes the list virtual BOOL CVirtualListView::PreCreateWindow(CREATESTRUCT& cs) { cs.style |= LVS_REPORT | LVS_OWNERDATA; return CListView::PreCreateWindow(cs); } |
Cod: |
// Just set the virtual list items count void CVirtualListView::FillList() { CListCtrl& list = GetListCtrl(); list.DeleteAllItems(); //... int nItemsCount = 999999; // this is just an example! list.SetItemCountEx(dwRecordsCount, LVSICF_NOSCROLL|LVSICF_NOINVALIDATEALL); } |
Cod: |
// LVN_GETDISPINFO notification handler function // Set the text and icon only for the items which are about to be drawn void CVirtualListView::OnGetdispinfo(NMHDR* pNMHDR, LRESULT* pResult) { LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR; LV_ITEM* pItem = &(pDispInfo)->item; if(pItem->mask & LVIF_TEXT) { // Set the text for the given item (use pItem->iItem, pItem->iSubItem, and pItem->pszText). } if(pItem->mask & LVIF_IMAGE) { // Set the icon for the given item (use pItem->iItem and pItem->iImage). } *pResult = 0; } |