Вторичный ярлык не срабатывает - PullRequest
3 голосов
/ 12 мая 2009

Я использую Delpho 2006. Сценарий:

На модуле данных у меня есть ActionList. У одного из действий есть комбинация клавиш Ctrl + F4, и я хочу использовать вторичную комбинацию клавиш Ctrl + W. Я попробовал все следующее:

Добавление Ctrl + W к списку действий SecondaryShortcut в IDE.

Добавление его в процедуру DataModuleCreate с использованием

ActFileCloseFile.SecondaryShortCuts.Add('Ctrl+W');

или

ActFileCloseFile.SecondaryShortCuts.AddObject('Ctrl+W',
  TObject(Menus.ShortCut(87, [ssCtrl])));

Использование обоих этих методов в процедуре Create или FormShow той формы, в которой она будет использоваться.

Первичный ярлык всегда работает, но не вторичный.

Когда я помещаю ActionList в основную форму вместо модуля данных, он работает, просто добавляя Ctrl + W в IDE. Что я делаю не так?

Ответы [ 4 ]

3 голосов
/ 12 мая 2009

Самое элегантное решение, найденное до сих пор, это:

В форме, которую вы хотите обработать SecondaryShortCut, добавьте это в событие OnShortCut:

procedure TMyForm.FormShortCut(var Msg: TWMKey; var Handled: Boolean);
begin
  Handled := dmDataModule.ActionList1.IsShortCut(Msg);
end;

Альтернатива:

(Это не реальное решение, а обходной путь.)

Поместите в форму список действий, действие которого идентично действию в модуле данных. В событиях execute и update он только перенаправляет события в действие модуля данных. В меню формы используется локальное действие.

В этом случае достаточно добавить Ctrl + W к свойству SecondaryShortCuts, используя IDE.

Очевидно, что при изменении действия над модулем данных я должен изменить также и все локальные действия.

1 голос
/ 09 августа 2014

Краткий ответ: ярлыки действий не автоматически запускаются через формы и модули данных.

Если вы будете следовать инструкциям, приведенным в вопросе, вы обнаружите, что даже первичные короткие пути не срабатывают. Это потому, что ключевой шаг был исключен из инструкций. Тот, который будет объяснять, почему ОП испытал первичное короткое замыкание, а не вторичное.

Если вы включите дополнительные шаги:

  • Добавить меню в форму.
  • И связать пункт меню с действием.

Тогда основной короткий путь сможет запустить действие. Это связано с тем, что компонент Action передает свои настройки в пункт меню (включая свойство ShortCut). Однако TMenuItem не реализует концепцию вторичных сокращений. Вот почему один работает, а другой нет.


Пауза для рассмотрения приложения с множеством форм и модулей данных; и следствие того, что быстрые сокращения действий могут сработать во всех из них. Должно быть совершенно очевидно, что они не могут автоматически запускать без явного кода, разрешающего это. Вы не хотели бы, чтобы фоновая форма выполняла кучу вещей, потому что ее настроенные сочетания клавиш оказывались нажатыми в контексте другой не связанной работы.

Документация указывает на преимущества размещения списков действий на модулях данных. Но, похоже, не дается никакого объяснения, как правильно использовать действия с ярлыками для модуля данных . Конечно, ничего не упоминается в ожидаемых местах, а именно: ShortCut и SecondaryShortcuts . (Я был бы разочарован, но мои ожидания в отношении достойной документации оказались довольно низкими.)

Итак ...

Что нужно сделать , чтобы получить действия с ярлыками, работающими с формами и модулями данных?

Я провел небольшое исследование и нашел несколько вариантов. Как всегда, оцените компромисс относительно того, чего вы пытаетесь достичь.

  • Когда вы опускаете список действий в (неосновной) форме, все ярлыки работают должным образом. Это наиболее распространенный сценарий и применяется, когда действия являются локальными и имеют специфическую форму.

  • Когда вы опускаете список действий в главной форме, все эти ярлыки могут запускаться из любой другой формы. Это отлично подходит для ярлыков во всем приложении, таких как открытие других форм.

ПРИМЕЧАНИЕ: Существует последовательность приоритетов в отношении того, где сначала проверяется сокращение. Таким образом, если активная форма имеет ярлык, совпадающий с соответствующим на главной форме, ярлык будет обрабатываться локально. И основная форма по понятным причинам не получит.

  • Когда форма проверяется, чтобы проверить, обрабатывает ли она ярлык, также проверяются все принадлежащие компоненты . (По сути, именно поэтому первые два выше работают.) Это означает, что простая установка Owner вашего модуля данных позволит соответствующим образом применить его ярлыки к выбранной вами форме.

т.е. Вместо:

Application.CreateForm(TDataModule1, DataModule1);

Вы можете использовать следующее:

DataModule1 := TDataModule1.Create(LocalForm);

Однако, поскольку у каждого экземпляра модуля данных может быть только один владелец: вам придется создать несколько экземпляров, чтобы позволить нескольким формам совместно использовать ярлыки. Будет ли это вариант, зависит от ваших обстоятельств. Однако вы также можете сделать основную форму владельцем вашего модуля данных, что будет в некоторой степени эквивалентно второму варианту, приведенному выше.

  • Последний вариант, обеспечивающий максимальный контроль, - это собственный ответ ОП. То есть Любая форма, которая должна поддерживать «внешние ярлыки», может обрабатывать событие OnShortCut с помощью следующего кода:

Как видно из примера кода, вы можете делегировать несколько списков действий в разных местах в соответствии с выбранным вами приоритетом.

procedure TMyForm.FormShortCut(var Msg: TWMKey; var Handled: Boolean);
begin
  Handled := DataModule1.ActionList3.IsShortCut(Msg);
  Handled := Handled or DataModule2.ActionList1.IsShortCut(Msg);
  Handled := Handled or DataModule1.ActionList1.IsShortCut(Msg);
end;
1 голос
/ 12 мая 2009

Не настоящее решение, но если вы создаете модуль данных из основной формы, он работает:

procedure TMainForm.FormCreate(Sender: TObject);
begin
  FDataModule := TMyDataModule.Create(self);
  TMyButton.Action := FDataModule.TheAction;
end;


procedure TMyDataModule.DataModuleCreate(Sender: TObject);
begin
  TheAction.SecondaryShortCuts.Add('Ctrl+W');
end;

Я думаю, что ярлыки обрабатываются формой, которая имеет текущий фокус. Так что, вероятно, у вас возникнут те же проблемы, если вы используете их в другой форме.

0 голосов
/ 13 мая 2009

Действие проглатывается формой ... Если вы хотите, чтобы вторичная форма / фрейм / модуль данных обрабатывал действие ... Сначала вы должны отключить Список действий из Первичного ...

Form1.ActionList1.State: = asSuspended;

DataModule1.ActionList1.State: = asNormal;

...