Работа с подменю в TToolBar: решение проблемы отображения состояния
В статье рассмотрим проблему отображения состояния подменю в компоненте TToolBar в среде разработки Delphi. При использовании кастомизированной панели инструментов с элементами меню (компоненты TToolButton с установленными свойствами MenuItem и Grouped), возникает проблема: после открытия подменю, свойство Down элемента TToolButton не отображает его текущее состояние. Это связано с тем, что информация о состоянии элемента хранится в приватном поле FMenuButton компонента TToolBar, доступ к которому не предоставляется.
Проблема и её описание
Когда пользователь кликает по элементу панели инструментов, свойство Down устанавливается в true. Однако, если у элемента есть подменю (свойство MenuItem установлено в true и свойство Grouped также true), то после открытия подменю вызывается обработчик OnAdvancedCustomDrawButton, но уже с Down в false. В результате, элемент панели инструментов отображается как неактивный, даже если подменю открыто.
Подтвержденный ответ
Для решения проблемы можно использовать один из двух подходов:
Модификация VCL
Откройте файл ComCtrls.pas.
Найдите определение класса TToolBar.
Добавьте в публичный раздел свойство MenuDropped, которое будет предоставлять доступ к приватному полю FMenuDropped.
property MenuDropped: Boolean read FMenuDropped;
Теперь вы можете проверить, открыто ли подменю, используя это свойство в коде.
Хак для доступа к полю FMenuDropped
Включите компиляцию с отладочными DCU.
Откройте ComCtrls.pas, найдите обработчик Paint класса TToolButton и установите точку останова.
Запустите приложение и используйте отладчик, чтобы найти смещение поля FMenuDropped.
В коде проверьте состояние подменю, используя полученное смещение.
if PBoolean(Integer(Toolbar1) + смещение)^ then
DoStuffIfMenuIsDropped
else
OtherStuffIfMenuIsNotDropped;
Альтернативный ответ
Используйте уведомление TBN_DROPDOWN, которое отправляется форме при клике на кнопку с выпадающим меню. Это позволяет отслеживать кнопку, которая запустила меню.
type
TForm1 = class(TForm)
...
private
FButtonArrowDown: TToolButton;
procedure WmNotify(var Msg: TWmNotify); message WM_NOTIFY;
...
uses
commctrl;
procedure TForm1.WmNotify(var Msg: TWmNotify);
begin
if (Msg.NMHdr.code = TBN_DROPDOWN) and
(LongWord(Msg.IDCtrl) = ToolBar1.Handle) then begin
FButtonArrowDown := FindButton(ToolBar1, PNMToolar(Msg.NMHdr).iItem);
inherited;
FButtonArrowDown := nil;
end else
inherited;
end;
procedure TForm1.ToolBar1AdvancedCustomDrawButton(...);
var
DroppedDown: Boolean;
begin
DroppedDown := Button = FButtonArrowDown;
...
end;
Пример использования классового помощника
Создайте классовый помощник для TToolBar, который добавит свойство MenuDropped для доступа к состоянию подменю.
TToolBarHelper = class helper for TToolBar
private
function GetMenuDropped: Boolean;
public
property MenuDropped: Boolean read GetMenuDropped;
end;
function TToolBarHelper.GetMenuDropped: Boolean;
begin
Result := Self.FMenuDropped;
end;
Теперь можно использовать это свойство в коде для проверки состояния подменю.
Заключение
В данной статье мы рассмотрели проблему отображения состояния подменю в компоненте TToolBar и предложили несколько решений. Важно помнить, что модификация VCL и использование хаков для доступа к приватным полям может быть не лучшим решением с точки зрения поддержки и совместимости кода. Альтернативный подход с использованием уведомлений TBN_DROPDOWN и классовых помощников может быть более предпочтительным.
В статье обсуждается проблема отображения состояния подменю в компоненте `TToolBar` в среде разработки Delphi и предложены способы её решения.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.