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

4
我正在开发一个Delphi XE7多平台应用程序,并希望使用一些热键/快捷方式。 TActionListTMainMenuTMenuBar都有属性用于分配快捷键。
我正在使用一个快捷键来在TTabControl上添加一个新的TTabItem。这个快捷键是Ctrl+T
因此,如果用户按下Ctrl+T,则在所述TTabControl上添加一个新选项卡——已正确工作。
但是,如果用户继续按住这两个键,则会创建多个选项卡。
只要用户持续按住这些键,即会触发快捷方式事件。
添加新标签仅是一个例子。我正在使用多个快捷键,希望只触发一次。
有没有办法只触发一次快捷键事件?
我尝试了定时器/等待特定时间。但如果用户想快速执行2个热键,则会出现问题。
感谢阅读,非常感谢所有的帮助。

这不仅与Firemonkey有关,VCL应用程序也是默认行为。在这里已经有人提问过,但你不能在FMX中使用被接受的解决方案。 - TLama
我认为除了使用定时器之外,没有其他解决方案,因为热键无法检测按键何时被按下,而是周期性地检查是否在特定时间按下了某些组合键。如果是,则触发事件。 - SilverWarior
2
这似乎不是值得花时间解决的问题。你的客户不会很快发现并停止长时间按键吗?其他软件供应商是否已经解决了这个问题?如果没有,那么为什么你要解决呢? - Rob Kennedy
@RobKennedy,我没有客户,因为这是我个人的项目(我是学生)。我出于好奇问了这个问题。但我想你是对的。如果它没坏,就不要修理它。 - ChrisB
你可以使用一个标志来禁用多重触发。仅当它被启用时才执行工作。在处理动作后设置这个禁用标志,并在正确的按键松开事件上清除。 - User007
1个回答

0
这是一个使用计时器解决此问题的示例,以便不会阻止用户连续使用多个不同操作。使用相同操作的速度取决于您的配置,但受系统键自动重复延迟间隔的限制。请参见代码注释。
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设置为大于系统键自动重复延迟间隔。


谢谢你的努力。我并不是在寻找一个计时器解决方案,但你的解决方案很好用。 - ChrisB
我知道你不是在寻找这种解决方案,但由于我已经在我的一个项目中有类似的东西在运行,所以我想分享一下。另外一个可能的方法是完全省略内置的热键功能,并使用Forms OnKeyDown和OnKeyUp事件重新实现类似的功能,同时启用KeyPreviewEnabled。在这种情况下,您将实现快捷方式功能,就像在之前的Delphi版本中常用的那样,这个功能并没有内置。实现这需要相当多的代码,并且不太容易使用。 - SilverWarior

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接