|
|
|||||||||||||||||||||||||||||
|
ComboBox с автозавершением (AutoComplete) по подстрокеИсточник: delphikingdom Андрей Чистяков
Постановка задачи В интернете достаточно много информации по реализации функции автозавершения вводимого в TextBox или ComboBox текста - так, как это сделано в диалоговом окне "Пуск / Выполнить". Данную функцию можно реализовать с помощью интерфейсов IAutoComplete/IAutoComplete2. Эти интерфейсы позволяют формировать список вариантов автозавершения, подбирая те строки, которые начинаются с введенного в поле редактирования текста, но не позволяют выбирать те строки, которые содержат введенный текст в любом месте строки (см. рис. 1) - во всяком случае в интернете я не нашел информации по этому вопросу. Поэтому пришлось делать свое выпадающее окно автозавершения. Рисунок1 В целом выпадающее окно должно вести себя точно так же, как и стандартное выпадающее окно ComboBox'а (это окно создается системой, его класс называется "ComboLBox"):
Второй пункт реализуется достаточно просто. Пункты первый и третий взаимосвязаны, и их я реализовать долгое время не мог. Родное выпадающее окно комбобокса (ComboLBox) судя по всему работает с применением захвата ввода от мыши (SetCapture/ReleaseCapture). Когда я попытался сделать свое выпадающее окно аналогичным образом, практически все получилось как задумано (комбобокс не терял фокус, форма не становилась неактивной), за единственным исключением - не работала полоса прокрутки в списке (в вопросе ¹ 57188 на Круглом столе тоже обсуждается эта проблема). Наконец, решение было найдено здесь. На основе этой статьи был сделан компонент TACComboBox. Тема показалась мне актуальной, поэтому я решил опубликовать результаты своих изысканий. Описание компонента Компонент имеет следующие published-свойства: property ACItems: TStrings; - список вариантов автозавершения; из строк, содержащихся в этом списке формируется список автозавершения, в зависимости от значения свойства ACType. type TAutoCompleteType = (actSimple, actSubString, actCustom); property ACType: TAutoCompleteType; - определяет алгоритм, по которому заполняется список автозавершения.
В принципе, для формирования списка автозавершения можно не пользоваться списком, заданным в свойстве ACItems. Для этого нужно написать наследника класса TACComboBox, в котором переопределить protected-метод PrepareACStrings. В параметре AText этому методу передается введенный в поле комбобокса текст; метод должен заполнить список FDropDown.Items (подробнее см. пример, прилагаемый к статье). Опишу некоторые детали реализации компонента; подробные комментарии есть в исходниках к статье.
Остальные методы классов на мой взгляд понятны, подробности см. в исходниках. Отмазки Отмазка №1. Все это затевалось в основном для того, чтобы сделать AutoComplete с возможностью подбора вариантов по подстроке. Я исходил из предположения, что интерфейсы IAutoComplete/IAutoComplete2 этого сделать не могут. Если окажется, что они таки могут, и я изобрел очередной велосипед в - простите великодушно, не кидайте в меня камень, лучше киньте ссылку, по которой есть такая информация. Впрочем, даже в этом случае, надеюсь, из моей реализации все равно можно извлечь какую-то пользу - например, можно в списке вариантов подсвечивать набранный текст, как это показано на рисунке в начале статьи. Отмазка №2. В принципе, можно в качестве выпадающего окна использовать не только листбокс. На мой взгляд, тема компонентов типа "поле ввода + кнопка + выпадающее окно" достаточно актуальна. Я попробовал на скорую руку вместо листбокса использовать календарь, на первый взгляд все работало как задумано. Но, с другой стороны, возможны и проблемы, связанные с тем, что фокус остается в комбобоксе и не переходит к выпадающему окну, поэтому как будет себя вести, например, TStringGrid с активным InplaceEdit'ом в роли выпадающего окна, я предсказывать не берусь. Отмазка №3. Данные исходики я рассматриваю скорее как первый набросок, чем как окончательный вариант компонента. Всесторонне обкатать компонент в боевом проекте я еще не успел, поэтому наверняка где-то что-то можно добавить/оптимизировать. Исходники К статье прилагаю архив. Компонент находится в файле _ACCombo.pas, устанавливается обычным образом (Component/Install component…). Демо-проект не требует установки компонента в IDE, там компонент создается в Run-Time, поэтому можно просто открыть .dpr и нажать F9, чтобы посмотреть, как оно работает. Исходники на Delphi 7, но, насколько мне известно, я не использовал никаких особенностей компилятора данной версии, которые помешали бы пользоваться компонентом в других версиях Delphi. Также, в соответствии с правилами Королевства, следует упомянуть и поблагодарить Владимира Папаева - для примера мне нужна была функция для представления числа прописью, я воспользовался его разработкой. Ссылки по теме
Файлы для загрузки
|
|