При работе с компонентом TComboEdit в Delphi (особенно в версиях 10.4 и выше) разработчики часто сталкиваются с ограниченным доступом к внутреннему списку (ListBox), который появляется при раскрытии комбинированного поля. В отличие от классического TComboBox, где список доступен через свойство Items, в TComboEdit список скрыт внутри реализации компонента.
Основные проблемы, с которыми сталкиваются разработчики: 1. Невозможность напрямую получить доступ к списку для управления фокусом 2. Ограниченное управление выбором элементов с клавиатуры 3. Автоматическое изменение текста в поле ввода при изменении ItemIndex
Решение через DropDown
Простейшее решение, которое предлагается в контексте - использование метода DropDown:
procedure TForm1.ComboEdit1KeyUp(Sender: TObject; var Key: Word;
var KeyChar: WideChar; Shift: TShiftState);
begin
if Key = vkDown then
ComboEdit1.DropDown;
end;
Однако, как отмечает автор вопроса, это решение неполное: - Список не получает фокус - Невозможно перемещаться по списку клавишами - Текст в поле ввода изменяется при установке ItemIndex
Продвинутое решение с доступом к внутреннему ListBox
Для полноценного управления списком необходимо получить доступ к внутреннему ListBox компонента TComboEdit. Это можно сделать через свойство Presentation:
uses
FMX.ComboEdit.Style, FMX.ListBox;
procedure TForm1.ComboEdit1KeyUp(Sender: TObject; var Key: Word;
var KeyChar: WideChar; Shift: TShiftState);
var
ListBox: TListBox;
begin
if Key = vkDown then
begin
ComboEdit1.DropDown;
// Получаем доступ к внутреннему ListBox
if ComboEdit1.Presentation is TStyledComboEdit then
begin
ListBox := TStyledComboEdit(ComboEdit1.Presentation).ListBox;
if Assigned(ListBox) then
begin
// Устанавливаем фокус на список
ListBox.SetFocus;
// Выбираем первый элемент (если список не пуст)
if ListBox.Count > 0 then
begin
ListBox.ItemIndex := 0;
// Предотвращаем изменение текста в ComboEdit
ComboEdit1.Text := ComboEdit1.Items[ListBox.ItemIndex];
end;
end;
end;
end;
end;
Альтернативное решение с обработкой клавиш
Для более полного управления можно создать наследник TComboEdit и переопределить обработку клавиш:
type
TMyComboEdit = class(TComboEdit)
protected
procedure KeyDown(var Key: Word; var KeyChar: WideChar; Shift: TShiftState); override;
end;
procedure TMyComboEdit.KeyDown(var Key: Word; var KeyChar: WideChar; Shift: TShiftState);
var
ListBox: TListBox;
begin
inherited;
if Key = vkDown then
begin
DropDown;
if Presentation is TStyledComboEdit then
begin
ListBox := TStyledComboEdit(Presentation).ListBox;
if Assigned(ListBox) then
begin
ListBox.SetFocus;
if ListBox.Count > 0 then
begin
ListBox.ItemIndex := 0;
// Сохраняем текущий текст без изменения
Text := Items[ListBox.ItemIndex];
end;
end;
end;
end
else if (Key = vkUp) and DroppedDown then
begin
// Обработка клавиши Up для перемещения по списку
if Presentation is TStyledComboEdit then
begin
ListBox := TStyledComboEdit(Presentation).ListBox;
if Assigned(ListBox) and (ListBox.ItemIndex > 0) then
begin
ListBox.ItemIndex := ListBox.ItemIndex - 1;
Text := Items[ListBox.ItemIndex];
end;
end;
end;
end;
Решение с использованием стилей
В более новых версиях Delphi можно модифицировать стиль компонента для добавления нужного поведения:
Создайте новый стиль для TComboEdit через редактор стилей
Найдите элемент ListBox в стиле
Добавьте обработчики событий для управления фокусом
Пример кода для модификации стиля:
procedure TForm1.ApplyComboEditStyle;
var
ListBox: TListBox;
begin
if ComboEdit1.Presentation is TStyledComboEdit then
begin
ListBox := TStyledComboEdit(ComboEdit1.Presentation).ListBox;
if Assigned(ListBox) then
begin
ListBox.OnKeyDown := ListBoxKeyDown;
ListBox.OnKeyUp := ListBoxKeyUp;
end;
end;
end;
procedure TForm1.ListBoxKeyDown(Sender: TObject; var Key: Word;
var KeyChar: WideChar; Shift: TShiftState);
begin
// Обработка клавиш в списке
if Key = vkReturn then
begin
// Действие при выборе элемента
ComboEdit1.DropDown := False;
Key := 0;
end;
end;
Заключение
Доступ к внутреннему списку TComboEdit возможен через свойство Presentation и приведение типа к TStyledComboEdit. Это позволяет реализовать полноценное управление списком, включая: - Установку фокуса на список при раскрытии - Управление выбором элементов с клавиатуры - Сохранение текста в поле ввода без автоматического изменения
Представленные решения дают гибкие варианты реализации требуемого поведения в зависимости от версии Delphi и конкретных требований приложения.
Контекст описывает проблему доступа к внутреннему списку ListBox компонента TComboEdit в Delphi и предлагает различные решения для управления этим списком, включая доступ через Presentation, переопределение обработки клавиш и модификацию стиля компонента
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.