Как как можно быстрее загрузить большой массив строк в элемент управления со списком MFC?
-
04-07-2019 - |
Вопрос
У меня есть массив из 1000 строк для загрузки в поле со списком.Каков самый быстрый способ загрузить массив строк в поле со списком?
Есть ли какой-то другой способ, кроме перебора списка строк, помещая каждую строку в поле со списком по одной?
И как скопировать данные поля со списком после загрузки примерно в 10 других полей со списком?
Решение
Если у вас есть 1000 строк, повторенных в 10 выпадающих списках, вы можете рассмотреть возможность использования выпадающего списка, нарисованного владельцем, который рисует строки на лету на основе индексов в вашем массиве, а не хранит их в выпадающем списке вообще. Намного быстрее, намного эффективнее памяти. Ознакомьтесь с методом DrawItem и структурой DRAWITEMSTRUCT в интерактивной справке. По сути, вам нужно сделать что-то вроде использования InitStorage и InsertString (как упомянуто NuSonic), чтобы создать 1000 пустых элементов в комбинированном списке и переопределить DrawItem извлечь и нарисовать требуемую строку, основываясь на индексе, так, как она должна быть нарисована.
Другие советы
Я не знаю какого-либо способа атомарной загрузки нескольких строк, но есть несколько вещей, которые вы можете сделать, чтобы сделать этот процесс более эффективным:
- Вызовите CComboBox::InitStorage перед добавлением элементов для предварительного выделения памяти.
- Используйте InsertString вместо AddString, чтобы предотвратить запуск сортировки при каждом добавлении (при условии, что стиль CBS_SORT включен)
Возможно, быстрее, чем CComboBox с DrawItem, будет владельцем . данные CListCtrl . Это также послужит вашей цели дублирования подмножества элементов в другие списки, поскольку может использоваться общий источник данных.
Я предлагаю это, потому что CComboBox из 1000 элементов не очень удобен в использовании.
Я рассмотрю возможность использования списка выбора вместо поля со списком для повышения производительности.
Общее практическое правило для повышения производительности при вставке множества элементов в список пользовательского интерфейса - вызывать перед вставкой и возвращать значение true после.
Вот правильный синтаксис
#define NB_ITEM 1000
#define ITEM_LENGTH 10
void CMFCComboDlg::InitMyCombo()
{
CString _strData;
m_cbMyCombo.SetRedraw( FALSE );
m_cbMyCombo.Clear();
m_cbMyCombo.InitStorage(NB_ITEM, ITEM_LENGTH);
for( int i = 0; i < NB_ITEM; i++ )
{
_strData.Format( L"Test %ld", i );
m_cbMyCombo.InsertString( i, _strData );
}
m_cbMyCombo.SetCurSel(0);
m_cbMyCombo.SetRedraw( TRUE );
}
РЕДАКТИРОВАТЬ: улучшить решение, включив в него предложение smacl
У меня была эта проблема, и я решил ее двумя способами, в зависимости от # пунктов. Настройка не рисовать и инициализировать хранение не имеет никакого значения для меня. Заставить нарисовать владельца тоже можно, но у меня была тонна комбо-боксов. Предполагая фиксированный список для каждого выпадающего списка, который не меняет содержимого, список устанавливается один раз.
Очень большой # Предметы: Сделал поле со списком просто / отключено с помощью SetWindowText, чтобы установить начальную строку, и маленькая кнопка рядом с ним открыла диалоговое окно, позволяющее выбрать элемент из списка управления в режиме отчета для данных, которые были бы в комбо окно (может быть сделано в диалоге).
Умеренные # элементы: Сделал пользовательский производный класс со списком, который переопределяет AddString, SelectString и обрабатывает OnDropDown. Когда вы добавляете элементы, он помещает их во временный вектор, а затем в SelectString (может также выполнить переопределение SetCurSel), он добавляет один элемент, который находит и выбирает. При выпадении вниз, он сбрасывает комбинированный список и добавляет все элементы и выбирает текущий выбранный. При падении выпадающего списка есть небольшое замедление, но при небольшом количестве предметов это не заметно.
Это заставило мои диалоги загружаться намного быстрее и все еще быть полностью функциональным без рисования владельцем. Р>