В статье рассмотрим проблему, с которой сталкиваются разработчики, использующие компонент TApplicationEvents в 32-битном приложении VCL на Delphi 11 для операционной системы Windows 10. Проблема заключается в том, что TApplicationEvents не реагирует на сообщение WM_MENURBUTTONUP, которое должно отправляться при клике правой кнопкой мыши по элементу меню TPopupMenu.
Описание проблемы
В документированных источниках Microsoft указано, что сообщение WM_MENURBUTTONUP отправляется при отпускании правой кнопки мыши, когда курсор находится на элементе меню. Вместо этого сообщения в случае клика правой кнопки отправляется WM_COMMAND, но оно приходит и при клике левой кнопки, что не подходит для задачи, когда требуется реакция исключительно на клик правой кнопки.
Решение проблемы для TMainMenu
Чтобы решить эту проблему для основного меню (TMainMenu), можно переопределить метод WndProc в классе формы следующим образом:
procedure TForm1.WndProc(var Message: TMessage);
begin
if Message.Msg = WM_MENURBUTTONUP then
begin
// Здесь код обработки клика правой кнопки
end
else
inherited
end;
Решение проблемы для TPopupMenu
Для всплывающего меню (TPopupMenu) необходимо создать собственное расширение класса TPopupList, переопределив метод WndProc:
type
TPopupListEx = class(TPopupList)
protected
procedure WndProc(var Message: TMessage); override;
end;
procedure TPopupListEx.WndProc(var Message: TMessage);
begin
if Message.Msg = WM_MENURBUTTONUP then
begin
// Здесь код обработки клика правой кнопки для TPopupMenu
end
else
inherited
end;
И не забудьте установить свойство TrackButton всплывающего меню в значение tbLeftButton.
Пример кода для TPopupMenu
procedure TPopupListEx.WndProc(var Message: TMessage);
begin
if Message.Msg = WM_MENURBUTTONUP then
begin
var MI := Menu.FindItem(Message.LParam, fkHandle);
if Assigned(MI) and InRange(Message.WParam, 0, MI.Count - 1) then
ShowMessageFmt('Menu item "%s" right clicked.', [MI.Items[Message.WParam].Caption]);
end
else
inherited
end;
И не забудьте, что для создания множества всплывающих меню, можно попробовать следующий подход (не полностью протестирован):
procedure TPopupListEx.WndProc(var Message: TMessage);
begin
if Message.Msg = WM_MENURBUTTONUP then
begin
for var X in PopupList do
if TObject(X) is TPopupMenu then
begin
// Код для обхода списка всплывающих меню
end;
end
else
inherited
end;
Необходимо помнить, что использование переопределения методов для обработки сообщений является специфическим решением для конкретных случаев и может потребовать дополнительной адаптации в зависимости от конкретного приложения и его структуры.
В статье был рассмотрен способ обработки сообщений, связанных с кликами правой кнопки мыши, в Delphi-приложениях. Предоставленные примеры кода могут служить отправной точкой для разработчиков, столкнувшихся с подобной задачей.
Статья рассматривает проблему обработки клика правой кнопкой мыши в всплывающем меню в среде Delphi 11, связанную с некорректной реакцией компонента `TApplicationEvents` на 32-битных приложениях VCL под Windows 10, и предлагает решения для основного меню
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS