• Переход в режим виртуальности

  • Количество элементов

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

  • Виртуальность это просто

    Для работы с виртуальным списком в простейшем случае достаточно следующего:

    • Создать виртуальный список

    • Вовремя заботиться о количестве элементов

    • По запросу списка заполнять элементы нужной информацией

    В некоторых случаях возможно понадобятся и более сложные вещи:

    • Кеширование

    • Сортировка

    • Быстрый поиск элементов

    Итак, обо всем по порядку.

    Переход в режим виртуальности

    Чтобы включить режим "виртуальности", необходимо установить стиль LVS_OWNERDATA. Текущая версия библиотеки элементов управления не позволяет переводить список из обычного режима в виртуальный "на лету", поэтому установку данного стиля необходимо делать при создании элемента. Если вы использует редактор диалога достаточно отметить переключатель Owner Data на вкладке More Style в окне свойств List Control. В случае применения класса СListView следует перекрыть PreCreateWindow.

    Вся прелесть виртуального режима в том, что список хранит не сами элементы, а только их общее количество, диапазон отображаемых в данный момент, и тому подобную "мелочь". Значения самих элементов (строковые метки, рисунки и т.п) запрашиваются у приложения непосредственно перед их отрисовкой на экране. Такой прием позволяет значительно сэкономить память и существенно повысить производительность, особенно для больших объемов данных.

    ПРИМЕЧАНИЕ

    В MSDN сказано, что после установки данного стиля, число элементов, которые сможет хранить список, будет ограничено максимальным значением DWORD (для обычных списков только int). Однако, все функции (в том числе и API) для работы со списком принимают int. Кроме этого, мне не удалось использовать более 100.000.000 элементов. Более того, в примере MSJ за ноябрь 1996 г. от Strohm Armstrong встречается именно эта магическая цифра. Отговорка, стандартна: "Сложно представить, что возникнет необходимость использовать больше". Нет вопросов, если бы использовалась хотя бы степень двойки, а так, IMHO, ограничение такой странной (круглой) цифрой выглядит коварным замыслом.

    Количество элементов

    Итак, список создан. Чтобы вставить в него элементы, достаточной задать их количество. Количество элементов в виртуальном списке задается одной из следующих функций.

    void CListCtrl::SetItemCount(int iCount);

    void CListCtrl::SetItemCountEx(int iCount, DWORD dwFlags = LVSICF_NOINVALIDATEALL);

    iCount

    новое количество элементов

    dwDlags

    Комбинация Флагов определяющая реакцию списка на изменение количества элементов.

    LVSICF_NOINVALIDATEALL Список не будет перерисован, пока добавленные элементы не окажутся с поле видимости.

    LVSICF_NOSCROLL Позиция скроллинга не изменится.

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

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

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

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

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

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

     LV_DISPINFO* pDispInfo = (LV_DISPINFO*)pNMHDR;

     LV_ITEM* pItem= &(pDispInfo)->item;

     CMyDocument* pDoc = GetDocument();

     int nIndex= pItem->iItem;

     if (pItem->mask & LVIF_TEXT) //требуется текст?

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

     if pItem->mask & LVIF_IMAGE) //требуется картинка

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

    }

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

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

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

    SendMessage(LVM_SETCALLBACKMASK, LVIS_STATEIMAGEMASK, 0);







     


    Главная | В избранное | Наш E-MAIL | Добавить материал | Нашёл ошибку | Наверх