辅助快捷方式不触发

发布于 2024-07-19 07:45:04 字数 580 浏览 13 评论 0原文

我正在使用 Delpho 2006。 场景:

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

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

使用其中一个方法将其添加到 DataModuleCreate 过程中,

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

或者

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

在将使用它的表单的 Create 或 FormShow 过程中使用这两种方法。

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

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

I am using Delpho 2006. The Scenario:

On the data module I have an ActionList. One of the actions has a shortcut Ctrl+F4 and I want to have a secondary shortcut Ctrl+W. I tried all of the following:

Adding Ctrl+W to the actions SecondaryShortcut list in the IDE.

Adding it in the DataModuleCreate procedure using either

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

or

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

Using both of these methods in the Create or FormShow procedure of the form where it will be used.

The primary shortcut always works, but not the secondary.

When I put the ActionList on the main form instead of the data module, it works by just adding Ctrl+W in the IDE. What do I do wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

天煞孤星 2024-07-26 07:45:04

到目前为止找到的最优雅的解决方案是这样的:

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

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

替代方案:(

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

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

在这种情况下,使用 IDE 将 Ctrl+W 添加到 secondaryShortCuts 属性就足够了。

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

The most elegant solution found so far is this:

On the form you want to handle the SecondaryShortCut, add this to the OnShortCut event:

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

Alternative:

(This is not a real solution, but a workaround.)

Put an action list on the form that has an identical action to the one on the data module. In its execute and update events it only forwards the events to the data module action. The menus on the form use the local action.

In this case it suffices to add Ctrl+W to the SecondaryShortCuts property using the IDE.

Obviously, when the action on the data module changes, I have to change all local actions too.

醉南桥 2024-07-26 07:45:04

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

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;

我认为快捷方式是由具有当前焦点的窗体处理的。 因此,如果您以其他形式使用它们,您可能会遇到同样的问题。

Not a real solution, but if you create the datamodule from within the mainform it works:

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;

I think the shortcuts are handled by the form that has the current focus. So yo will probably get the same problems if you are using them in another form.

青萝楚歌 2024-07-26 07:45:04

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

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

如果包含额外的步骤:

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

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


停下来考虑一个具有多种表单和数据模块的应用程序; 以及行动捷径是否可以在所有这些人身上触发的含义。 很明显,如果没有明确的代码允许,它们不应该能够自动触发。 您不希望后台表单执行大量操作,因为其配置的快捷键恰好是在其他不相关工作的上下文中按下的。

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

那么......

应该做什么来获得跨表单和数据模块的快捷操作?

我做了一些调查并找到了一些选择。 与往常一样,评估与您想要实现的目标相关的权衡。

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

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

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

  • 当测试表单以查看它是否处理快捷方式时,还将检查所有拥有的组件。 (这实际上就是上面前两个方法起作用的原因。)这意味着只需适当地设置数据模块的 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;

Short Answer: Actions short-cuts do not automatically fire across forms and data-modules.

If you follow the instructions in the question, you'll find that not even the primary short-cut fires. This is because a key step has been left out of the instructions. One that will serve to explain why OP experienced the primary short-cut firing and not the secondary one.

If you include the extra steps:

  • Add a menu to the form.
  • And link a menu-item to the action.

Then the primary short-cut will be able to fire the action. This is because the Action component pushes its settings to the menu item (including the ShortCut property). However, TMenuItem does not implement the concept of secondary short-cuts. Which is why one works and not the other.


Pause to consider an application with many forms and data-modules; and the implication if action short-cuts could fire across all of them. It should be fairly obvious that they should not be able automatically fire without explicit code to permit it. You wouldn't want a background form doing a bunch of things because its configured short-cut keys happen to be pressed in the context of other unrelated work.

The documentation points out the benefit of putting action lists on data-modules. But doesn't seem to offer any explanation how to use actions with short-cuts on a data-module correctly. Certainly nothing is mentioned in the expected places, namely: ShortCut and SecondaryShortcuts. (I'd be disappointed, but my expectations of decent documentation have been dragged quite low.)

So...

What should be done to get actions with short-cuts working across forms and data-modules?

I have done a bit of investigation and found a few options. As always, evaluate the trade-off's relative to what you are trying to achieve.

  • When you drop an action list on a (non-main) form, all the short-cuts work as expected. This is the most common scenario and applies when the actions are local and form specific.

  • When you drop an action list on the main form, all those short-cuts will be able to fire from any other form. This is great for application-wide short-cuts such as opening other forms.

NOTE: There is a prioritisation sequence as to where a short-cut is tested first. So if the active form has a short-cut matching one on the main form, the short-cut will be processed locally. And the main form understandably won't get it.

  • When a form is tested to see if it handles a short-cut, all owned components are also checked. (This is in fact why the first two above work.) This means that simply setting the Owner of your data-module appropriately will allow its short-cuts to apply to your chosen form.

I.e. Instead of:

Application.CreateForm(TDataModule1, DataModule1);

You can use the following:

DataModule1 := TDataModule1.Create(LocalForm);

However, since each instance of a data-module can have only one owner: you would have to create multiple instances to let multiple forms share the short-cuts. Whether this is an option depends on your circumstances. However, you could also make the main form the owner of your data-module which would be somewhat equivalent to the second option above.

  • The final option which provides the most control is OP's own answer. I.e. Any form that needs to support "external short-cuts" can handle the OnShortCut event with the following code:

As can be seen in the code sample you can delegate to multiple action lists in different locations according to the priority you choose.

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;
好菇凉咱不稀罕他 2024-07-26 07:45:04

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

Form1.ActionList1.State := asSuspished;

DataModule1.ActionList1.State := asNormal;

The action is getting swallowed by the form...If you want a secondary form/frame/datamodule to handle the action...You have to disable the Actionlist from the Primary first...

Form1.ActionList1.State := asSuspended;

DataModule1.ActionList1.State := asNormal;

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文