[MFC] Liste virtuale

Despre MFC, ATL si alte biblioteci C++ de la Microsoft (forum moderat)
Post Reply
User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

[MFC] Liste virtuale

Post by Ovidiu Cucu » 04 Jan 2008, 17:04

Problema
Atunci cand numarul de inregistrari de incarcat intr-un control listview devine foarte mare, timpul necesar creste corespunzator. Ce optimizare s-ar putea face in acest caz?

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:
  1. Setam stilul LVS_OWNERDATA.
  2. Setam numarul de item-uri cu CListCtrl::SetItemCountEx.
  3. 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.

Exemplu

Code: Select all

// 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);
}

Code: Select all

// 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);   
}

Code: Select all

// 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;
}
Note
  • O implementare concreta de listview virtual puteti gasi in sursele de la proiectul LogExpert
<< Back to MFC index



Post Reply