Переход от MDI (Multiple Document Interface — интерфейс с множественными документами) к вложенной форме под вкладкой PageControl может вызвать ряд проблем, в том числе и с обработкой комбинаций клавиш. При использовании MDI, обработка комбинаций клавиш, связанных с действиями (actions), происходила корректно. Однако после перехода к структуре с вкладками, обработка стала осуществляться по-другому: вместо действий (actions) срабатывали комбинации, назначенные на пункты главного меню (TMainMenu).
Описание проблемы
При работе в режиме MDI, когда у вас был TActionList с заданными комбинациями клавиш, события выполнения действий (TActionList execute event) срабатывали корректно. После перехода к структуре с вложенными формами под вкладками PageControl, комбинации клавиш, назначенные на пункты главного меню, стали срабатывать вместо действий, определенных в TActionList. Если отключить пункты главного меню (TMenuItems), то действия из TActionList начинают работать нормально.
unit Unit2;
interface
uses
// ... используемые модули ...
type
TForm2 = class(TForm)
ActionList1: TActionList;
Action1: TAction;
Action2: TAction;
Action3: TAction;
Label1: TLabel;
// ... другие компоненты ...
end;
var
Form2: TForm2;
implementation
{$R *.dfm}
// ... реализация процедур выполнения действий ...
end.
Решение проблемы
Для решения проблемы с обработкой комбинаций клавиш, необходимо переопределить метод IsShortCut в основном форме, который будет сначала проверять, существует ли соответствующее действие в TActionList текущей вкладки, прежде чем обращаться к пунктам главного меню. Вот пример такого переопределения:
function TForm1.IsShortCut(var Message: TWMKey): Boolean; override;
function DispatchShortCut(const Owner: TComponent): Boolean;
var
I: Integer;
Component: TComponent;
ts: TTabSheet;
begin
Result := False;
for I := 0 to Owner.ComponentCount - 1 do
begin
Component := Owner.Components[I];
ts := (TCustomActionList(Component).Owner.GetParentComponent as TTabSheet);
if (ts.TabIndex = Self.PageControl1.ActivePageIndex) then
if Component is TCustomActionList then
begin
if TCustomActionList(Component).IsShortCut(Message) then
begin
Result := True;
Exit;
end;
end
else
begin
Result := DispatchShortCut(Component);
if Result then
Break;
end;
end;
end;
begin
Result := DispatchShortCut(Self);
if not Result then
Result := inherited;
end;
Комментарий пользователя
Пользователь благодарит за ответ и просит уточнить, как должна быть реализована функция IsShortCut для TCustomForm, а также задает вопрос о том, как функция определяет, какая именно дочерняя форма открыта, и как она знает, к какой форме следует передать комбинацию клавиш.
Объяснение
Приведенный выше код — это лишь пример, который демонстрирует общий подход к решению проблемы. Вам необходимо будет адаптировать его под конкретные нужды вашего приложения. Функция DispatchShortCut перебирает все дочерние компоненты формы и проверяет, соответствует ли текущая комбинация клавиш какой-либо из действий в TActionList текущей активной вкладки. Если такое действие найдено, то выполняется соответствующее действие, и дальнейший поиск прекращается.
Обратите внимание, что для полноценной реализации вам потребуется дополнительно обработать случаи, когда вкладки могут быть закрыты или перемещены, а также другие возможные сценарии использования вашего приложения.
Проблема заключается в изменении обработки комбинаций клавиш при переходе от MDI-интерфейса к использованию вложенных форм с вкладками в Delphi.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS