Trigger Hotkey / Shortcut Event only once

931 views Asked by At

I'm developing a Delphi XE7 multi-platform application and want to use some hotkeys / shortcuts.

TActionList, TMainMenu and TMenuBar all have properties to assign ShortCuts.

I am using an shortcut to add a new TTabItem on a TTabControl. That ShortCut is Ctrl + T.

So if the user presses Ctrl + T a new tab is added on said TTabControl - working correctly.

However if the user keeps holding down those 2 keys multiple tabs are created as well.

The shortcut event is triggered as long as the user keeps holding down those keys.

Adding a new tab is only an example. I am using multiple shortcuts that I only want to trigger once.

Is there any way to only trigger a shortcut event once?

I tried timers / waiting a specific amount of time. But that causes problems if the user wants to quickly perform 2 hotkeys.

Thanks for reading and I appreciate all help.

1

There are 1 answers

2
SilverWarior On BEST ANSWER

Here is an example of how to solve this using Timer so that it doesent block users from using multiple different actions in a row. The speed for using of the same action depends on your configuration but is limited by system Key Autorepeat delay interval. See in code comments.

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;

NOTE: Set timer interval to 1 ms. And don't forget to set ActionCooldownValue to be greater than system key autorepeat delay interval