仅触发一次热键/快捷方式事件

Posted

技术标签:

【中文标题】仅触发一次热键/快捷方式事件【英文标题】:Trigger Hotkey / Shortcut Event only once 【发布时间】:2015-01-09 12:42:25 【问题描述】:

我正在开发一个 Delphi XE7 多平台应用程序并想使用一些热键/快捷方式。

TActionListTMainMenuTMenuBar 都具有分配快捷方式的属性。

我正在使用快捷方式在TTabControl 上添加新的TTabItem。该快捷方式是 Ctrl + T

因此,如果用户按下 Ctrl + T,则会在所述 TTabControl 上添加一个新选项卡 - 正常工作。

但是,如果用户一直按住这 2 个键,也会创建多个选项卡。

只要用户一直按住这些键,就会触发快捷事件。

添加新标签只是一个示例。我正在使用多个我只想触发一次的快捷方式。

有没有办法只触发一次快捷事件?

我尝试了计时器/等待特定的时间。但如果用户想要快速执行 2 个热键,这会导致问题。

感谢阅读,感谢所有帮助。

【问题讨论】:

它不仅仅与 Firemonkey 有关。这是 VCL 应用程序中的默认行为。也。一直是asked here,但您将无法使用已接受的 FMX 解决方案。 我认为除了使用计时器之外没有其他解决方案,因为热键不会检测何时按下键,但会定期检查是否在特定时间按下了某些键组合。如果是事件被触发。 这似乎不是一个值得花时间解决的问题。您的客户不会很快就明白这一点并停止长时间按住按键吗?这是任何其他软件供应商已解决的问题吗?如果不是,那你为什么要这样做? @RobKennedy 我没有任何客户,因为这是我正在从事的个人项目(我是学生)。我出于好奇问了这个问题。但我想你是对的。如果它没有坏,请不要修复它。 您可以使用一个标志来禁用多重射击。只要启用它就可以完成工作。在处理完动作后设置这个禁用标志并清除右键事件。 【参考方案1】:

这是一个如何使用 Timer 解决此问题的示例,以便它不会阻止用户连续使用多个不同的操作。使用相同动作的速度取决于您的配置,但受系统 Key Autorepeat 延迟间隔的限制。见代码 cmets。

const
  //Interval after which the action can be fired again
  //This needs to be greater than system key autorepeat delay interval othervise
  //action event will get fired twice
  ActionCooldownValue = 100;

implementation

...

procedure TForm2.MyActionExecute(Sender: TObject);
begin
  //Your action code goes here
  I := I+1;
  Form2.Caption := IntToStr(I);
  //Set action tag to desired cooldown interval (ms before action can be used again )
  TAction(Sender).Tag := ActionCooldownValue;
end;

procedure TForm2.ActionList1Execute(Action: TBasicAction; var Handled: Boolean);
begin
  //Check to see if ActionTag is 0 which means that action can be executed
  //Action tag serves for storing the cooldown value
  if Action.Tag = 0 then
  begin
    //Set handled to False so that OnExecute event for specific action will fire
    Handled := False;
  end
  else
  begin
    //Reset coldown value. This means that user must wait athleast so many
    //milliseconds after releasing the action key combination
    Action.Tag := ActionCooldownValue;
    //Set handled to True to prevent OnExecute event for specific action to fire
    Handled := True;
  end;
end;

procedure TForm2.Timer1Timer(Sender: TObject);
var Action: TContainedAction;
begin
  //Itearate through all actions in the action list
  for Action in ActionList1 do
  begin
    //Check to see if our cooldown value is larger than zero
    if Action.Tag > 0 then
      //If it is reduce it by one
      Action.Tag := Action.Tag-1;
  end;
end;

注意:将计时器间隔设置为 1 毫秒。并且不要忘记将 ActionCooldownValue 设置为大于系统键自动重复延迟间隔

【讨论】:

感谢您的努力。我不是在寻找计时器解决方案,但您的解决方案工作正常。 我知道您不是在寻找这种解决方案,但由于我已经在我的一个项目中进行了类似的工作,我想我可以分享它。无论如何,另一种可能的方法是完全省略内置的 HotKey 功能,并在启用 KeyPreview 时使用 Forms OnKeyDown 和 OnKeyUp 事件重新实现类似的功能。在这种情况下,您将实现快捷功能,因为它通常用于以前版本的 Delphi 中,该版本尚未内置此功能。实现此功能需要相当多的代码,而且不太容易使用。

以上是关于仅触发一次热键/快捷方式事件的主要内容,如果未能解决你的问题,请参考以下文章

不用注册热键方式在Delphi中实现定义快捷键(又简单又巧妙,但要当前窗体处在激活状态)

markdown OS X热键 - 快捷方式

用于发布当前文件的 Visual Studio 键盘快捷键/热键

访问 PyQt5 组件的内置快捷方式?

C# 设定菜单快捷键

Visio 学习笔记 —— Visio 的键盘快捷方式