При разработке пользовательских интерфейсов на Delphi часто возникает необходимость использования выпадающих меню для различных элементов управления, в том числе для кнопок. В этом руководстве мы рассмотрим, как создать простое и эффективное выпадающее меню для TButton, используя стандартные компоненты Delphi.
Проблема
Пользователь столкнулся с проблемой, при которой при нажатии на кнопку TButton открывается выпадающее меню, но если нажать на кнопку повторно, меню не закрывается, а открывается снова. Это происходит из-за того, что при повторном вызове обработчика события MouseUp вызывается процедура DropMenuDown, которая снова открывает меню.
Решение
Для решения этой проблемы можно использовать переменную, которая будет отслеживать, было ли меню открыто последним нажатием на кнопку. Если меню было открыто, и нажатие произошло снова в течение короткого промежутка времени (например, 100 миллисекунд), то можно считать, что это попытка закрыть меню, и отменить дальнейшие действия.
Вот пример кода, который реализует данное решение:
unit Unit4;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus, Vcl.StdCtrls;
type
TForm4 = class(TForm)
PopupMenu1: TPopupMenu;
Button1: TButton;
// Другие компоненты...
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
private
// Переменная для отслеживания времени последнего закрытия меню
cMenuClosed: Cardinal;
public
end;
var
Form4: TForm4;
implementation
{$R *.dfm}
procedure DropMenuDown(Control: TControl; PopupMenu: TPopupMenu);
var
APoint: TPoint;
begin
APoint := Control.ClientToScreen(Point(0, Control.ClientHeight));
PopupMenu.Popup(APoint.X, APoint.Y);
end;
procedure TForm4.Button1Click(Sender: TObject);
begin
DropMenuDown(Button1, PopupMenu1);
// Запоминаем время открытия меню
cMenuClosed := GetTickCount;
end;
procedure TForm4.Button1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
if (Button = mbLeft) and not ((cMenuClosed + 100) < GetTickCount) then
begin
// Отменяем дальнейшие действия, если меню было открыто и нажатие произошло в течение 100 мс
ReleaseCapture;
end;
end;
procedure TForm4.FormCreate(Sender: TObject);
begin
// Инициализируем переменную временем начала работы формы
cMenuClosed := 0;
end;
end.
Альтернативное решение
Для более универсального решения можно использовать следующий подход, который предполагает хранение ссылок на последний элемент управления и меню, а также время их последнего закрытия. Это позволяет избежать необходимости вносить изменения в код формы, за исключением вызова функции ButtonMenu в обработчике события Click кнопки:
unit ButtonMenus;
interface
uses
Vcl.Controls, Vcl.Menus;
procedure ButtonMenu(Control: TControl; PopupMenu: TPopupMenu);
implementation
uses
System.Classes, WinApi.Windows;
var
LastClose: DWord;
LastPopupControl: TControl;
LastPopupMenu: TPopupMenu;
procedure ButtonMenu(Control: TControl; PopupMenu: TPopupMenu);
var
Pt: TPoint;
begin
if (Control = LastPopupControl) and (PopupMenu = LastPopupMenu) and (GetTickCount - LastClose < 100) then begin
// Если меню уже открыто для этого элемента управления, закрываем его
LastPopupControl := nil;
LastPopupMenu := nil;
end else begin
PopupMenu.PopupComponent := Control;
Pt := Control.ClientToScreen(Point(0, Control.ClientHeight));
PopupMenu.Popup(Pt.X, Pt.Y);
// Запоминаем время открытия меню и ссылки на элемент управления и меню
LastClose := GetTickCount;
LastPopupControl := Control;
LastPopupMenu := PopupMenu;
end;
end;
end.
Использование этого решения в коде формы:
procedure TForm1.Button1Click(Sender: TObject);
begin
ButtonMenu(Button1, PopupMenu1);
end;
Заключение
Создание выпадающего меню для TButton в Delphi может быть простым и эффективным, если использовать предложенные решения. Важно помнить о том, что обработка событий нажатия и отпускания кнопки мыши позволяет реализовать логику открытия и закрытия меню. Приведенные примеры кода могут быть адаптированы под конкретные нужды разработчика, обеспечивая при этом удобство использования и соответствие стандартам пользовательского интерфейса.
В данном контексте описывается создание и оптимизация работы выпадающего меню для кнопки `TButton` в среде разработки Delphi, включая решения для корректного закрытия меню при повторном нажатии на кнопку.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.