3

我正在使用 Delpho 2006。场景:

在数据模块上,我有一个 ActionList。其中一个操作有一个快捷键 Ctrl+F4,我想要一个辅助快捷键 Ctrl+W。我尝试了以下所有方法:

将 Ctrl+W 添加到 IDE 中的操作 SecondaryShortcut 列表中。

使用以下任一方法将其添加到 DataModuleCreate 过程中

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

或者

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

在将要使用它的窗体的 Create 或 FormShow 过程中使用这两种方法。

主要快捷方式始终有效,但次要快捷方式无效。

当我将 ActionList 放在主窗体而不是数据模块上时,只需在 IDE 中添加 Ctrl+W 即可。我做错了什么?

4

4 回答 4

3

迄今为止发现的最优雅的解决方案是:

在要处理 SecondaryShortCut 的表单上,将其添加到 OnShortCut 事件:

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

选择:

(这不是真正的解决方案,而是一种解决方法。)

在表单上放置一个与数据模块上的动作相同的动作列表。在其执行和更新事件中,它仅将事件转发给数据模块操作。表单上的菜单使用本地操作。

在这种情况下,只需使用 IDE 将 Ctrl+W 添加到 SecondaryShortCuts 属性即可。

显然,当数据模块上的操作发生变化时,我也必须更改所有本地操作。

于 2009-05-12T07:36:11.347 回答
1

不是一个真正的解决方案,但如果您从主窗体中创建数据模块,它可以工作:

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;

我认为快捷方式由具有当前焦点的表单处理。所以如果你以另一种形式使用它们,你可能会遇到同样的问题。

于 2009-05-12T07:21:13.023 回答
1

简短回答:操作快捷方式不会跨表单和数据模块自动触发。

如果您按照问题中的说明进行操作,您会发现即使是主要的捷径也不会着火。这是因为说明中遗漏了一个关键步骤。这将有助于解释为什么 OP 经历了主要的捷径射击而不是次要的捷径。

如果您包括额外的步骤:

  • 向表单添加菜单。
  • 并将菜单项链接到操作。

然后主快捷方式将能够触发该动作。这是因为 Action 组件将其设置推送到菜单项(包括ShortCut属性)。但是,TMenuItem没有实现二级快捷方式的概念。这就是为什么一个有效而另一个无效的原因。


暂停考虑具有许多表单和数据模块的应用程序;以及动作捷径是否会在所有这些方面触发的含义。很明显,如果没有明确的代码允许,它们不应该能够自动触发。您不希望后台表单做很多事情,因为它配置的快捷键恰好在其他不相关工作的上下文中被按下。

文档指出了将操作列表放在数据模块上的好处。但似乎没有提供任何解释如何正确地在数据模块上使用带有快捷方式的操作。当然,在预期的地方没有提到任何内容,即:ShortCutSecondaryShortcuts。(我会很失望,但我对体面文档的期望被拖得很低。)

所以...

应该怎么做才能使用跨表单和数据模块的快捷方式执行操作?

我做了一些调查,发现了一些选择。与往常一样,评估相对于您要实现的目标的权衡。

  • 当您将操作列表放在(非主)表单上时,所有快捷方式都会按预期工作。这是最常见的场景,适用于本地操作和特定形式的操作。

  • 当您在主窗体上放置一个操作列表时,所有这些快捷方式都可以从任何其他窗体触发。这对于应用程序范围的快捷方式非常有用,例如打开其他表单。

注意:对于首先测试捷径的位置有一个优先顺序。因此,如果活动表单在主表单上有一个与主表单匹配的快捷方式,则该快捷方式将在本地处理。可以理解,主要形式不会得到它。

  • 当测试表单以查看它是否处理快捷方式时,还会检查所有拥有的组件。(这实际上就是上述前两个有效的原因。)这意味着只需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;
于 2014-08-09T15:55:22.003 回答
0

动作被表单吞没了...如果您想要辅助表单/框架/数据模块来处理该动作...您必须首先从主表单中禁用动作列表...

Form1.ActionList1.State := asSuspended;

DataModule1.ActionList1.State := asNormal;

于 2009-05-13T13:36:38.627 回答