简短回答:操作快捷键不会自动跨表单和数据模块触发。
如果您按照问题中的说明进行操作,甚至主要快捷键也无法触发。这是因为指令中遗漏了一些关键步骤,这可以解释为什么OP经历了主要的快捷键触发而没有次要的快捷键。
如果您包括以下额外步骤:
- 添加菜单到表单中。
- 将菜单项链接到操作。
那么主要的快捷键将能够触发操作。这是因为Action组件将其设置推送到菜单项(包括ShortCut属性)。但是,TMenuItem不实现次要快捷键的概念。这就是为什么一个起作用而另一个不起作用的原因。
请暂停一下,考虑一个具有许多表单和数据模块的应用程序,以及如果操作快捷方式可以跨所有表单和数据模块触发的含义。显然,它们不应该在没有明确允许的代码的情况下自动触发。您不希望背景表单因其配置的快捷键在其他无关工作的上下文中被按下而执行一堆操作。
文档指出将操作列表放在数据模块上的好处。但似乎没有提供如何在数据模块上
正确使用带有快捷键的操作的解释。当然,在预期的位置上没有提到任何内容,即:
快捷键和
次要快捷键。 (我会感到失望,但是我对良好文档的期望已经非常低了。)
所以...
如何使跨表单和数据模块的快捷操作正常工作?
我进行了一些调查,并找到了几个选项。像往常一样,要根据您想要实现的目标评估权衡。
注意:有一个优先级顺序,确定首先测试快捷方式的位置。因此,如果活动表单具有与主表单上匹配的快捷键,则会在本地处理快捷键。主表单则无法获取它。
- 当测试表单是否处理快捷键时,所有所属组件也会被检查。(这就是前两个方法有效的原因。) 这意味着简单地设置数据模块的
Owner
属性为所选表单即可使其快捷键生效。
即:不要这样做:
Application.CreateForm(TDataModule1, DataModule1);
您可以使用以下内容:
DataModule1 := TDataModule1.Create(LocalForm);
然而,由于每个数据模块实例只能有一个所有者:您必须创建多个实例才能让多个表单共享快捷方式。这是否可行取决于您的情况。但是,您还可以将主表单作为数据模块的所有者,这在某种程度上相当于上述第二个选项。
提供最多控制权的最终选项是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;