Why use "hotkey, If"?

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Why use "hotkey, If"?

14 Sep 2018, 17:17

I came accross the command Hotkey, If, <Expression>. But when I used it, I started to wonder what the benefits are. This is what I initially coded. It is not functional since it is only a snip out of a larger code:

Code: Select all

#If GuisAreActive()
#If

GuisAreActive(){
  global hGui
  Return (WinActive("ahk_id " GetNPPHwnd()) or WinActive("ahk_id " hGui))
}

SetHotkeys(){
  Hotkey, If, GuisAreActive()
  Hotkey, F9, RunAHK
  Hotkey, If
}

RunAHK(){
  ;Code
}
But instead I think (not tested) this would do the same Job:

Code: Select all

SetHotkeys(){
  Hotkey, $F9, RunAHK
}

RunAHK(){
  global hGui
  If (WinActive("ahk_id " GetNPPHwnd()) or WinActive("ahk_id " hGui)){
    Send %A_ThisHotkey%
    Return 
  }
  ;Code
}
The former seems to be more flexible then the previous. And it has in total less lines of code.
So could someone please point out what the benefits of Hotkey, If, <Expression> are compared to shortcut the hotkey if a certain condition doesn't apply?
ciao
toralf
lexikos
Posts: 9592
Joined: 30 Sep 2013, 04:07
Contact:

Re: Why use "hotkey, If"?

14 Sep 2018, 17:54

I think you mean "latter" rather than "former", and If !(WinActive...) rather than If (WinActive...).

Why would you ever use #If or #IfWinActive when you could use a normal If or If WinActive()? The answer is the same here.

Disabling a hotkey is not the same as sending it after it fires. The latter has side-effects, especially when you do it incorrectly. It is error-prone due to the difference in syntax and several modifiers that don't apply to Send. For example, your second code would send the literal text "$F9". If you Send {F9}, it will have the side-effect of marking the event as generated by AutoHotkey, and it will send the up event immediately after the down event (not when you release the key).

Regarding code size, the first code has an unfair disadvantage because the condition is wrapped inside a function. This is necessary only to avoid repetition. Repetition of the expression is necessary because Hotkey If is unable to create new expressions. But since the expression is just a call to a function with no parameters, it actually isn't necessary at all in this case. Instead of creating an expression with #If and referencing it with Hotkey, you can use the function directly:

Code: Select all

GuisAreActive(){
  global hGui
  Return (WinActive("ahk_id " GetNPPHwnd()) or WinActive("ahk_id " hGui))
}

SetHotkeys(){
  f := Func("GuisAreActive")  ; Separate assignment needed due to v1 limitations.
  Hotkey, If, % f
  Hotkey, F9, RunAHK
  Hotkey, If
}

RunAHK(){
  ;Code
}
This is a complete working example in AutoHotkey v2-a099 (though Hotkey "IfWinActive" would be more suitable in this case since A_ScriptHwnd never changes):

Code: Select all

SetHotkeys()
ListHotkeys

SetHotkeys() {
    Hotkey "If", () => WinActive("ahk_id " A_ScriptHwnd)
    Hotkey "$F9", "RunAHK"
    Hotkey "If"
}

RunAHK() {
    MsgBox "Pressed F9 in the script's window."
}
However, if you use an anonymous function, you must pass a reference to the same anonymous function whenever you want to modify hotkeys originally created under that function. In other words, you can't just repeat the expression () => whatever. If you need to modify the hotkeys (anywhere other than in SetHotkeys), you're better off with a separate function.

If you use a closure (i.e. if the expression references a local variable or parameter of SetHotkeys), calling the SetHotkeys function again would create a totally new hotkey variant, since the object passed to Hotkey "If" would be different each time. It is the same with bound functions in v1 and v2.

I presume the reason for not using IfWinActive and ahk_group in the original script is that the GUI and/or NPP HWND may change.
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: Why use "hotkey, If"?

15 Sep 2018, 16:07

lexikos wrote:I think you mean "latter" rather than "former", and If !(WinActive...) rather than If (WinActive...).
correct.
lexikos wrote:IWhy would you ever use #If or #IfWinActive when you could use a normal If or If WinActive()? The answer is the same here.
true
lexikos wrote:Disabling a hotkey is not the same as sending it after it fires. The latter has side-effects, especially when you do it incorrectly. It is error-prone due to the difference in syntax and several modifiers that don't apply to Send. For example, your second code would send the literal text "$F9". If you Send {F9}, it will have the side-effect of marking the event as generated by AutoHotkey, and it will send the up event immediately after the down event (not when you release the key).
thank you for the inside.
lexikos wrote:Regarding code size, the first code has an unfair disadvantage because the condition is wrapped inside a function. This is necessary only to avoid repetition. Repetition of the expression is necessary because Hotkey If is unable to create new expressions. But since the expression is just a call to a function with no parameters, it actually isn't necessary at all in this case. Instead of creating an expression with #If and referencing it with Hotkey, you can use the function directly:
thank you for this advice, I”ll try it. I would like to use parameters, but maybe I can make it work with bound function.
lexikos wrote:If you use a closure (i.e. if the expression references a local variable or parameter of SetHotkeys), calling the SetHotkeys function again would create a totally new hotkey variant, since the object passed to Hotkey "If" would be different each time. It is the same with bound functions in v1 and v2.
I was very excited to read about closure, but realized later that it is only available in V2. I”m still on V1, so I guess I have to try bound function or use a_thishotkey to have different conditions for different Hotkeys in the expression/function.
lexikos wrote:I presume the reason for not using IfWinActive and ahk_group in the original script is that the GUI and/or NPP HWND may change.
not exactly it is simplified condition. I plan to have more complex conditions that betend on different status within the script. Thus the expression if a Hotkey should be active has to be evaluated at key press. Or at least this I what I want to achieve. Additionally the Hotkeys can be altered during execution in a settings dialog.

Thank you very much for your assistance
ciao
toralf
lexikos
Posts: 9592
Joined: 30 Sep 2013, 04:07
Contact:

Re: Why use "hotkey, If"?

15 Sep 2018, 18:35

Another important difference I forgot to mention before is that "Hotkey If" allows the creation of an unlimited number of hotkey variants, whereas using a global hotkey which checks its own condition for action requires that the one hotkey handles every "variant". That means re-implementing the ability to turn each pseudo-variant on/off, and you can't specify different settings for each pseudo-variant, such as B/B0, Pn, Tn or In (InputLevel).

However, because you can create an unlimited number of variants, you might have to be careful with how many you create, since you can't delete variants. For instance, if you re-register all hotkey variants using new bound functions (for "Hotkey If") every time the program's configuration changes, you would actually be duplicating the entire set of hotkey variants. Instead, you would need to reuse any bound functions whose parameters have not changed. (Alternatively, you can use your own custom function object to allow you to modify the parameters later.)
toralf
Posts: 868
Joined: 27 Apr 2014, 21:08
Location: Germany

Re: Why use "hotkey, If"?

16 Sep 2018, 03:25

Custom function objects and classes are currently beyond my abilities.
A workaround to avoid too many variants could be a reload of the script after the hotkeys have changed.
ciao
toralf

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Araphen, DaveT1, Joey5, KolaBorat, Thorlian and 163 guests