Элемент ComboBox с функцией Autocomplete

В современных приложениях с графическим интерфейсом можно часто увидеть поля редактирования строк с выпадающими списками, которые показывают набор строк с подходящим текстом. Это могут быть ранее введённые строки (например: URL-адреса в командной строке веб-браузера) или имена файлов, как в стандартных диалогах оболочки Windows. В составе Windows API имеется функция SHAutoComplete, которая позволяет назначить элементу EDIT в собственном приложении выпадающий список файлов или адресных строк URL.Но есть задачи, в который необходимо иметь в выпадающем списке заранее определённый массив строк, к примеру: справочник из таблицы базы данных. Количество строк в таком справочнике может составлять десятки тысяч, и возникает необходимость в быстрой загрузке такого объёма информации и в быстром доступе к нужным строкам. Если воспользоваться для этого стандартным элементом COMBOBOX, то эффективность его работы с большим количеством данных будет довольно низкой, потому как программный интерфейс работы с оконными элементами Windows основан на передаче им системных сообщений (функция SendMessage). Это вызывает существенное замедление в работе программы при передаче большого количества данных. Таким образом, чтобы создать эффективный механизм загрузки большого количества данных в элемент интерфейса, необходимо эти данные передавать без использования системных функций типа SendMessage, а записывать их непосредственно в динамический массив элемента. В данной статье я собираюсь представить элемент собственной разработки, который выглядит как обычный COMBOBOX, но позволяет загружать большое количество строк намного быстрее, чем стандартный элемент Windows. К тому же этот элемент обладает дополнительной функцией Autocomplete, которая выполняет автоматическое добавление текста в конец вводимой строки.Так выглядит структурная диаграмма данного элемента…

Теперь рассмотрим более подробно каждую из составных частей этой диаграммы.

Массив строк - это динамический массив, созданный на основе шаблона CArray библиотеки MFC. При загрузке данных в список элемента, эти данные записываются в указанный массив и хранятся там.

Поле ввода - это стандартный элемент редактирования EDIT для ввода строки. Во время ввода текста в данное поле, по фрагменту введённой строки производится поиск подходящей строки в динамическом массиве строк. Если в массиве присутствует подходящая строка, текст в поле редактирования автоматически дополняется символами строки из массива.

Выпадающий список - это субкласс от стандартного элемента LISTBOX, который отображает список строк, хранящихся в массиве. С помощью полосы прокрутки или с помощью клавиатуры можно перемещаться по списку, выбирая ту или иную позицию. Текст выделенной позиции синхронно отображается в поле ввода.

Обработчик клавиатуры - это класс с процедурой обработки событий от клавиатуры при вводе текста или при навигации по выпадающему списку. О перехвате событий от клавиатуры в приложениях Windows мной была написана отдельная статья. Она так и называется: Перехват нажатия клавиш в приложениях Windows.

Сам класс CQuickComboBox является наследником от базового класса CListBox библиотеки MFC и при его использовании в классе окна диалога, он привязывается к стандартному элементу интерфейса LISTBOX.В окне программы данный элемент выглядит следующим образом…

Связывание экземпляров класса библиотеки MFC с элементами интерфейса Windows выполняется с помощью функций DDX. Функции DDX также используются для обмена данными между элементами интерфейса и переменными заданного типа внутри класса окна диалога. Для класса CQuickComboBox специально написаны две функции: DDX_QuickComboCtrl и DDX_QuickComboText. Функция DDX_QuickComboCtrl предназначена для связывания экземпляра класса CQuickComboBox с элементом типа LISTBOX (не COMBOBOX!). А функция DDX_QuickComboText используется для обмена текстовой информацией между элементом окна диалога и переменной типа CString. В программном коде это выглядит следующим образом…

void CQuickComboDlg::DoDataExchange(CDataExchange* pDX) 
{
  CDialog::DoDataExchange(pDX);
  DDX_QuickComboCtrl(pDX, IDC_QUICKCOMBO, m_QuickCombo);
  DDX_QuickComboText(pDX, IDC_QUICKCOMBO, m_Text);
}

В данном примере список строк загружается из ресурсов приложения. Для этого реализована процедура загрузки строк из текстового файла, включённого в состав ресурсов программы.

Исходный код данного демонстрационного приложения можно загрузить отсюда: quickcombobox_src.zip