"Использование ListView в режиме виртуального списка" - читать интересную книгу автора (Чадов Тимофей)

Демонстрационная программа – 161 KB

Исходные тексты – 39 KB

Все программисты делятся на тех, кто повсеместно применяет виртуальный режим, и тех, кто о нем даже и не слышал. Конечно, это шутка, как и любая с долей … шутки-)

На таких сайтах как CodeGuru, есть несколько неплохих примеров применения виртуальных списков. Однако, многие программисты, с которыми мне приходится сталкиваться, лишь изредка прибегают к этой технике, ошибочно считая, что это если не извращение, то уж по крайней мере излишество. Многие заблуждаются, считая, что применение виртуальных списков необходимо только лишь в случаях больших массивов данных, например, при отображении информации из баз данных. Конечно это справедливо, однако, о чем действительно часто забывают – применение виртуальных списков позволяет не только повысить производительность, но и обеспечивает разделение данных и их представлений. Последнее, на мой взгляд, не менее важно.

Конечно, как и везде, нужно знать меру. Не стоит сломя голову бежать переписывать свой код, если требуется вывести диалоговое окно для выбора десятков элементов: cойдет и обычный подход. Однако, если логика вашего приложения основана на применении представления на основе ListView с широкими возможностями по добавлению|удалению|редактированию, да к тому же большого объема записей, – стоит задуматься о виртуальном режиме.

Итак, в этой статье я попробую приподнять завесу тайны над этим чудесным режимом. Вы готовы к путешествию в виртуальность?

Содержание элементов

Итак, виртуальный список хранит очень мало информации. За заполнение элементов перед отрисовкой отвечает приложение. Для этого список посылает уведомление LVN_GETDISPINFO. Обработчик несложно добавить, воспользовавшись ClassWizzard.

В обработчике уведомления LVN_GETDISPINFO необходимо проверить, какая информация требуется, и заполнить соответствующие поля.

В следующем примере показан один из способов реализации.

void CMyListView::OnGetdispinfo(NMHDR* pNMHDR, LRESULT* pResult) {

 LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;

 LV_ITEM* pItem= amp;(pDispInfo)-gt;item;

 CMyDocument* pDoc = GetDocument();

 int nIndex= pItem-gt;iItem;

 if (pItem-gt;mask amp; LVIF_TEXT) //требуется текст?

 strcpy(pItem-gt;pszText, pDoc-gt;GetItemText(pItem-gt;iSubItem, nIndex));

 if pItem-gt;mask amp; LVIF_IMAGE) //требуется картинка

  pItem-gt;iImage= pDoc-gt;GetItemImage(nIndex);

}

Здесь GetItemText и GetItemImage функции класса документа, возвращающие текст меток и номер изображения требуемого элемента соответственно.

По умолчанию виртуальный список не хранит информацию поля state, за исключением двух флагов LVIS_SELECTED и LVIS_FOCUSED. Это приводит к тому, что использование иконок состояния (state image) невозможно. Однако эту ситуацию легко исправить. Необходимо использовать сообщение LVM_SETCALLBACKMASK, позволяющее задать маску для хранимой списком информации об элементах.

// Разрешаем использовать иконки состояния

SendMessage(LVM_SETCALLBACKMASK, LVIS_STATEIMAGEMASK, 0);