#If Wrong

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
arcticir
Posts: 694
Joined: 17 Nov 2013, 11:32

#If Wrong

09 Jul 2015, 01:20

[Moderator's note: Topic moved from Bug Reports.]

The following examples should show "31", but now shows "311", it is more out of a pop-up event.

Code: Select all

#If a(3)
f1:: MsgBox

#If a(1)
f1 up:: MsgBox
#If

a(a){
static s
ToolTip,% s:=s a
}
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: #If Wrong

09 Jul 2015, 02:46

Due to a design quirk of AutoHotkey, the expression may be evaluated up to two times for a single keyboard or mouse event.
As far as Im aware it has been solved in the new version of AHK.
Recommends AHK Studio
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: #If Wrong

09 Jul 2015, 03:29

No, it clearly still happens for key-up hotkeys as arcticir demonstrated.

This is by design. When you press the key, AutoHotkey needs to know whether the "f1 up" hotkey is active. To determine that it needs to evaluate the expression. When you release the key, it needs to know whether the hotkey should fire, so re-evaluates the expression. It does this for other #IfWin directives as well, but since they don't have any side-effect (like concatenating to a variable and displaying a tooltip), you don't notice. This is one reason the documentation says:
... the expression should be written to complete quickly and without side-effects.
arcticir, why did you believe it should show "31"?
guest3456
Posts: 3462
Joined: 09 Oct 2013, 10:31

Re: #If Wrong

09 Jul 2015, 05:18

This might be good to add to the docs to show an example of a code WITH side-effects which exemplifies the problem (or just link to this thread)

arcticir
Posts: 694
Joined: 17 Nov 2013, 11:32

Re: #If Wrong

09 Jul 2015, 11:57

Only two events.

Because I need to get real hotkey event, Down and up.
If there are three, prove that a certain event does not exist.
I had to use a lot of code to identify which is the real event.
guest3456
Posts: 3462
Joined: 09 Oct 2013, 10:31

Re: #If Wrong

09 Jul 2015, 15:31

arcticir:
lexikos wrote: This is by design. When you press the key, AutoHotkey needs to know whether the "f1 up" hotkey is active. To determine that it needs to evaluate the expression.
@lex
But why does AHK need to know whether the UP hotkey is active on the downpress? Can it just query that on the release event?

lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: #If Wrong

09 Jul 2015, 19:32

When there is only a key-up hotkey, AutoHotkey still needs to block the key-press and key-release, otherwise the key would get stuck in the "pressed" state. If the key-up hotkey is context-sensitive, AutoHotkey must only block the key-press if the key-up hotkey is likely to be activated. (If conditions change and the key-up hotkey doesn't fire, the key-release should still be blocked.)

Code: Select all

; Produces "1" on press and "1" on release.

#If a(1)
f1 up:: MsgBox

a(a){
static s
ToolTip,% s:=s a
}
If AutoHotkey already knows for certain that the hotkey will be fired, it doesn't need to check - for instance, if you add a global F1:: or F1 up:: hotkey, the result is "1" only on release:

Code: Select all

f1::MsgBox global

#If a(1)
f1 up:: MsgBox
 
a(a){
static s
ToolTip,% s:=s a
}
Note that if there is a key-down hotkey which is eligible to fire, the condition for the key-up hotkey doesn't need to be evaluated:

Code: Select all

; Produces "3" on press and "1" on release.

#If a(3)
f1:: MsgBox

#If a(1)
f1 up:: MsgBox

a(a) {
static s
ToolTip,% s:=s a
return a=3  ; f1:: is eligible to fire.
}
There are some cases where it appears the expression probably doesn't need to be evaluated but it is anyway. For instance, if the key-up hotkey has the ~tilde prefix, the key-press doesn't need to be blocked and therefore the expression probably doesn't need to be evaluated on key-press:

Code: Select all

; Currently produces "31" on press and "1" on release.

#If a(3)
~f1:: MsgBox
 
#If a(1)
~f1 up:: MsgBox
 
a(a){
static s
ToolTip,% s:=s a
}
This might be for simplicity (since hotkeys without tilde must be done this way) or a side-effect of the design of key-up hotkeys; I can't say for sure as I haven't analyzed it in depth.

It might be possible to eliminate the extra evaluation as a matter of optimization, but the fact remains that #If is not intended for hooking keyboard events. There are still some other cases where the expression must be evaluated even if the key isn't being pressed/released. For example, the condition for F1 & F2:: might be evaluated when you press the F1 key, so AutoHotkey knows whether to block that key-press. (The use of F1 as a "prefix" key causes it's native function to be blocked by default.)

Code: Select all

; Produces "1" whenever F1 is pressed.

#If a(1)
f1 & f2::MsgBox

a(a) {
static s
ToolTip,% s:=s a
return true  ; Causes F1 to act as a prefix key.
}
The expression might not be evaluated if some other custom combination has been defined and is known to be active. For example:

Code: Select all

f1 & f3::MsgBox

#If a(1)
f1 & f2::MsgBox

a(a) {
static s
ToolTip,% s:=s a
return true
}
I had already written some amendments to the #If documentation before this topic began, but haven't uploaded the changes yet.
arcticir wrote:Because I need to get real hotkey event, Down and up.
Use hotkeys to detect hotkey events. That's not what #If is for.
guest3456
Posts: 3462
Joined: 09 Oct 2013, 10:31

Re: #If Wrong

09 Jul 2015, 22:17

thanks, very thorough

arcticir
Posts: 694
Joined: 17 Nov 2013, 11:32

Re: #If Wrong

10 Jul 2015, 00:25

I can not find the reason, "# If" must accept the false event.
I need to record an event, rather than take the initiative to detect, because a lot of hotkeys are addScript () Add, I do not know what hotkey.

Maybe because you do not encounter more complex state? For instance:

Code: Select all

#If key_z OR (KH_Shut_r
	? (KH_r[1]? (KH_r[2],KH_r[3]? KH_r[3]:=0: KH_r[1]:=0): Black(KH_r))
	: 1)
	*rbutton:: Down("r")
	*rbutton up:: up("r")

#If key_z OR (KH_Shut_m
	? (KH_m[1]? (KH_m[2],KH_m[3]? KH_m[3]:=0: KH_m[1]:=0): Black(KH_m))
	: 1)
	*mbutton:: Down("m")
	*mbutton up:: up("m")

#If key_z OR (KH_Shut_L
	? (KH_L[1]? (KH_L[2],KH_L[3]? KH_L[3]:=0: KH_L[1]:=0): White(KH_L))
	: 1)
	*LButton:: Down("L")
	*LButton up:: up("L")
#If


Black(f){
	static
	f[1]:=A_Tick++
	mousegetpos,,,id
	WinGetTitle,t,% "ahk_id " id
	if (f["id"] = id) and (t2 = t)
	{
		return  f[2],f[2]?"":f[3]:=1
	}
	else 
	{ 

		f["id"]:=id, t2:=t
		WinGetClass,c,% "ahk_id " id
		WinGet,e,processpath,% "ahk_id " id
		if f["c"][c] 
			or (f["t*"] and  (t ~= f["t*"]))
			or (f["e*"] and  (e ~= f["e*"]))
			or (f["c*"] and  (c ~= f["c*"])) 
			or f["e"][e] or f["t"][t]
		return f[2]:=0,f[3]:=1
	}   
	return  f[2]:=1
}

White(f){
	static
	f[1]:=A_Tick++
	mousegetpos,,,id
	WinGetTitle,t,% "ahk_id " id
	if (f["id"] = id) and (t2=t)
		return  f[2],f[2]?"":f[3]:=1 
	else
	{
		f["id"]:=id, t2 := t
		WinGetClass,c,% "ahk_id " id
		WinGet,e,processpath,% "ahk_id " id
		if f["c"][c] 
			or (f["t*"] and  (t ~= f["t*"]))
			or (f["e*"] and  (e ~= f["e*"]))
			or (f["c*"] and  (c ~= f["c*"])) 
			or f["e"][e] or f["t"][t]
		return f[2]:=1
	}
	return  f[2]:=0,f[3]:=1
}

In this example, I need to record what the hotkey is pressed bounce, and needs to be recorded if it is triggered, but I am most painful is that I must also use a lot of code to determine which events are false.
Because even if a hotkey is not triggered, when other hotkey triggered, it can be used as a modifier key, so you need to know what does not trigger hotkeys, and no bounce.
and these data must be "#if" record.
This is my mouse gestures code.
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: #If Wrong

10 Jul 2015, 02:54

arcticir, I understood practically none of your post.
arcticir
Posts: 694
Joined: 17 Nov 2013, 11:32

Re: #If Wrong

10 Jul 2015, 03:40

Sorry, my English is poor.

I need the real key events,
Even "#if" returned result is "false"

If you want to know which hotkey was pressed, no bounce
You will all keyboard and mouse buttons are detected it?
arcticir
Posts: 694
Joined: 17 Nov 2013, 11:32

Re: #If Wrong

10 Jul 2015, 04:25

This is an example that can be run:

you first press the left button, it does not trigger the hotkey.
then press right, then bounce
lbutton here will serve as the modifier key, the result should be: RL
But now only R

Code: Select all

global key:=[],name


#if d("r")
rbutton::  Down("r")
#if d("L")
LButton::  Down("L")

#if u("L")
LButton up::  up("L")

#if u("r")
rbutton up::  up("r")
#if 

Down(s){

}

up(s){
	for i,n in key
		if n.Down and !n.if
			s.=i
	ToolTip,% "You press " s
	Return
}

d(s){
	if (s="r")
	a:=true
	if !IsObject(key[s])
	key[s]:=[]
	key[s].Down:=true
	key[s].if:=a
	Return a
}

u(s){
	a:=key[s].if
	key[s].Down:=false
	key[s].if:=false
	Return a
}
User avatar
RobertL
Posts: 546
Joined: 18 Jan 2014, 01:14
Location: China

Re: #If Wrong

10 Jul 2015, 04:37

See Lexikos's post
for reference only
我为人人,人人为己?
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: #If Wrong

10 Jul 2015, 19:26

I think I didn't emphasize this enough:
I wrote:Use hotkeys to detect hotkey events. That's not what #If is for.
Do not use #If to detect keyboard events. It is specifically intended for evaluating whether a hotkey is active, not to detect that it has been pressed.

If you need to always detect the key and sometimes block it, use two hotkeys. Change the state (i.e. key.Down) from each hotkey, not from the #If expression.

Code: Select all

#If condition
RButton::MsgBox RButton hotkey
#If
~RButton::MsgBox RButton non-hotkey
If you just need to know whether the button is pressed, use GetKeyState.

Code: Select all

#If GetKeyState("LButton", "P")
RButton::MsgBox LR
#If GetKeyState("RButton", "P")
LButton::MsgBox RL
... but if you're just trying to detect custom combinations of two keys/buttons, use a custom combination hotkey.

Code: Select all

~LButton & RButton::MsgBox LR
~RButton & LButton::MsgBox RL
arcticir
Posts: 694
Joined: 17 Nov 2013, 11:32

Re: #If Wrong

11 Jul 2015, 07:46

Sorry, my example error.
If I need to be more complex hotkey combinations it?
For example: {RButton} + {A}{SHIFT}{F12}{Tab}

Code: Select all

global key:=[],name
 ;Assume all keyboard and mouse buttons are set to hotkey
 #if d("r")
rbutton::  Down("r")
#if d("A")
A::  Down("A")
;BCDEF....
#if d("Z")
Z:: Down("Z")
;....
F1::  Down("F1")
;F2F3....
F24:: Down("F24")
;....
Numpad0::  Down("Numpad0")
AppsKey:: Down("AppsKey")

;....

 
#if u("r")
rbutton up::  up("r")
#if d("A")
A up::  up  Down("A")
;................................
#if 
 

Down(s){
 
}
 
up(s){
	for i,n in key
		if n.Down and !n.if
			s.=i
	ToolTip,% "You press " s

/*	
For instance: 	
{RButton} + {A}{SHIFT}{F12}{Tab}
{RButton} + {B}{A}{C}
{RButton} + {MButton}{XButton2}{Home}
Different hotkey combinations to trigger different commands.
*/
	Return
}
 
d(s){
	if (s="r")
	a:=true
	if !IsObject(key[s])
	key[s]:=[]
	key[s].Down:=true
	key[s].if:=a
	Return a
}
 
u(s){
	a:=key[s].if
	key[s].Down:=false
	key[s].if:=false
	Return a
}
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: #If Wrong

11 Jul 2015, 17:26

1. Stop using #If to detect key presses and releases.
2. This is the Bug Reports forum. Post in Ask for Help if you need help.
arcticir
Posts: 694
Joined: 17 Nov 2013, 11:32

Re: #If Wrong

11 Jul 2015, 20:29

Why do you ignore the "#IF" Significance, determine whether the trigger. Now use trigger recording as a trigger condition.
why do you think "record" is equivalent to "detect key presses and releases."
Do you think "detect key presses and releases." Can determine whether the trigger?
Do you think the trigger results of other hotkeys to as judged by the condition, it violated the "#if" significance?

you list a lot of explanation, but no one can prove that "#if" must accept the false event.
reported here it was my fault, because we can not communicate, but apparently I do not need help.
lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: #If Wrong

11 Jul 2015, 22:53

All explanation aside, you are using #If in a manner in which it is not intended to be used.

I have insufficient patience to continue arguing across this language barrier. You can either take my advice and stop using #If in this manner, or not.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: haomingchen1998, ReyAHK and 263 guests