簡単な回答: アクションのショートカットは、フォームとデータ モジュール全体で自動的に起動しません。
質問の指示に従うと、主要なショートカットでさえ起動しないことがわかります。これは、重要な手順が説明から除外されているためです。OPが二次的なショートカット発火ではなく一次的なショートカット発火を経験した理由を説明するのに役立つもの。
追加の手順を含める場合:
- フォームにメニューを追加します。
- メニュー項目をアクションにリンクします。
次に、プライマリ ショートカットがアクションを起動できるようになります。これは、アクション コンポーネントがその設定をメニュー項目 (ShortCut
プロパティを含む) にプッシュするためです。ただし、TMenuItem
セカンダリ ショートカットの概念は実装されていません。これが、一方が機能し、他方が機能しない理由です。
多くのフォームとデータモジュールを含むアプリケーションを検討するために一時停止します。アクションのショートカットがそれらすべてで発生する可能性があるかどうかの意味。許可する明示的なコードがなければ、自動的に起動できないことは明らかです。構成されたショートカット キーが他の無関係な作業のコンテキストで押されることがあるからです。
ドキュメントは、アクション リストをデータ モジュールに配置する利点を指摘しています。しかし、データモジュールでショートカットを使用してアクションを正しく使用する方法については、何の説明も提供していないようです。確かに、期待される場所、つまりShortCutおよびSecondaryShortcutsには何も言及されていません。(がっかりするかもしれませんが、まともなドキュメントに対する期待はかなり低くなりました。)
そう...
フォームとデータモジュール全体で動作するショートカットでアクションを取得するにはどうすればよいですか?
私は少し調査を行い、いくつかのオプションを見つけました。いつものように、達成しようとしているものとの相対的なトレードオフを評価してください。
(メイン以外の) フォームにアクション リストをドロップすると、すべてのショートカットが期待どおりに機能します。これは最も一般的なシナリオであり、アクションがローカルでフォーム固有の場合に適用されます。
アクション リストをメイン フォームにドロップすると、これらすべてのショートカットが他のフォームから起動できるようになります。これは、他のフォームを開くなど、アプリケーション全体のショートカットに最適です。
注:ショートカットが最初にテストされる場所に関しては、優先順位付けの順序があります。そのため、アクティブ フォームにメイン フォームのショートカットと一致するショートカットがある場合、ショートカットはローカルで処理されます。そして、当然のことながら、メインフォームはそれを取得しません。
- ショートカットを処理するかどうかを確認するためにフォームがテストされると、所有されているすべてのコンポーネントも確認されます。(実際、これが上記の最初の 2 つが機能する理由です。) つまり
Owner
、データ モジュールの を適切に設定するだけで、そのショートカットを選択したフォームに適用できるようになります。
つまり、代わりに:
Application.CreateForm(TDataModule1, DataModule1);
以下を使用できます。
DataModule1 := TDataModule1.Create(LocalForm);
ただし、データ モジュールの各インスタンスは所有者を 1 人しか持てないため、複数のフォームでショートカットを共有するには、複数のインスタンスを作成する必要があります。これがオプションであるかどうかは、状況によって異なります。ただし、メインフォームをデータモジュールの所有者にすることもできます。これは、上記の2番目のオプションと多少同等です。
- ほとんどの制御を提供する最後のオプションは、OP 自身の答えです。つまり、「外部ショートカット」をサポートする必要があるフォームは、次のコードで 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;