Разработчики, использующие Delphi для создания интерфейсов, часто сталкиваются с необходимостью создания многоуровневых меню, где выделен может быть только один элемент. В данной статье мы рассмотрим, как можно решить эту проблему, используя свойства GroupIndex и RadioItem, а также альтернативные подходы для работы с большим количеством элементов.
Описание проблемы
Пользователь столкнулся с задачей создания многоуровневого выпадающего меню (PopupMenu) в Delphi, где должно быть возможно выделение только одного элемента в целом по всему меню, включая все подменю. Свойства GroupIndex и RadioItem, предназначенные для группировки элементов, не работали за пределами соответствующих подменю. Пользователю требовалось быстрое решение, так как меню содержало 4x14 элементов, и постоянный перебор всех элементов меню и подменю казался неэффективным.
Подтвержденное решение
Одно из решений заключается в добавлении всех 56 элементов меню в один ActionList и назначении всем элементам одинакового GroupIndex. Это позволяет автоматически снять выделение со всех элементов меню при выборе нового, независимо от их уровня вложенности.
Пример кода:
var
ActionList: TActionList;
begin
ActionList := TActionList.Create(nil);
// Добавляем действия в ActionList, задаем GroupIndex
// ...
// Создаем PopupMenu и связываем его с ActionList
PopupMenu1 := TPopupMenu.Create(nil);
PopupMenu1.Action = ActionList;
end;
Функция для проверки элемента меню:
procedure TForm1.CheckMenuItem(Item: TMenuItem);
begin
if not Item.Checked then
begin
// Снимаем выделение со всех элементов в группе
UncheckMenu(Item.GetParentMenu.Items, Item.GroupIndex);
// Выделяем текущий элемент
Item.Checked := True;
end;
end;
procedure TForm1.UncheckMenu(Menu: TMenuItems; GroupIndex: Byte);
var
I: Integer;
begin
for I := 0 to Menu.Count - 1 do
begin
with Menu[I] do
begin
if RadioItem and (GroupIndex = GroupIndexOf(Menus)) then
Checked := False;
if not SubMenuItems.Count = 0 then
UncheckMenu(SubMenuItems, GroupIndex);
end;
end;
end;
Альтернативное решение
Как альтернатива использованию ActionList, можно применить следующий подход. Создаем процедуру CheckMenuItem, которая принимает элемент меню и отвечает за снятие выделения со всех элементов группы и выделение текущего элемента.
procedure TForm1.CheckMenuItem(Item: TMenuItem);
begin
if (not Item.Checked) and Item.RadioItem and (Item.GroupIndex <> 0) then
begin
// Снимаем выделение со всех элементов в группе
UncheckMenu(Item.GetParentMenu.Items, Item.GroupIndex);
Item.Checked := True;
end;
end;
procedure TForm1.UncheckMenu(MenuItems: TMenuItems; GroupIndex: Byte);
var
I: Integer;
begin
for I := 0 to MenuItems.Count - 1 do
with MenuItems[I] do
if RadioItem and (GroupIndex = GroupIndex) then
Checked := False;
end;
procedure TForm1.UncheckAllInGroup(Menu: TMenuItem; GroupIndex: Byte);
var
SubMenu: TMenuItem;
I: Integer;
begin
for I := High(Menu.Items) downto Low(Menu.Items) do
begin
SubMenu := Menu.Items[I];
if (SubMenu.RadioItem) and (SubMenu.GroupIndex = GroupIndex) then
SubMenu.Checked := False;
if (SubMenu.HasSubMenus) then
UncheckAllInGroup(SubMenu, GroupIndex);
end;
end;
При вызове CheckMenuItem для какого-либо элемента меню, он будет автоматически снять выделение со всех элементов в той же группе, независимо от их расположения в иерархии меню.
Таким образом, разработчики могут эффективно управлять выделением элементов в многоуровневых выпадающих меню, используя предложенные методы.
Проблема заключается в необходимости реализации функционала, при котором в многоуровневом выпадающем меню PopupMenu в Delphi можно выделить только один активный элемент во всем меню, включая все подменю.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.