Trigger event only once with mouse wheel.

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
KilliK
Posts: 255
Joined: 10 Mar 2016, 21:19

Trigger event only once with mouse wheel.

19 Jan 2017, 17:26

Hello.

How can I make WheelUp or WheelDown when used as hotkeys, to trigger an event only once after I stop scrolling?
For example:

Code: Select all

wheelup::
send {A}
return
it keeps sending the letter A as as long I keep scrolling upwards. what I want is to send the letter one time only every time I start and finish the scrolling, regardless of its duration.
I thought to use getkeystate but I read it doesnt work with the mouse wheel. so how can I achieve this?
User avatar
Exaskryz
Posts: 2882
Joined: 17 Oct 2015, 20:28

Re: Trigger event only once with mouse wheel.

19 Jan 2017, 17:55

You could use something like this:

Code: Select all

Wheelup::
If (A_TimeSincePriorHotkey<200) ;;; Edit: I have redacted the rest of this line: && (A_PriorHotkey=A_ThisHotkey) ; the latter is optional, but allows you to fire a different hotkey just prior to activating this one on purpose
{ ; brackets are optional in this because it's only one line tied to the If statement
Send {A}
}
return
Last edited by Exaskryz on 19 Jan 2017, 18:08, edited 1 time in total.
User avatar
KilliK
Posts: 255
Joined: 10 Mar 2016, 21:19

Re: Trigger event only once with mouse wheel.

19 Jan 2017, 18:01

thanks but it doesnt have any effect, it keeps sending the key while scrolling.
User avatar
Exaskryz
Posts: 2882
Joined: 17 Oct 2015, 20:28

Re: Trigger event only once with mouse wheel.

19 Jan 2017, 18:07

(Oh, I also have no idea why I used the && (A_PriorHotkey=A_ThisHotkey)... I can't think of a good reason for it now! That would make the first attempt at firing this hotkey fail, I think... . I might have been going for (A_PriorHotkey!=A_ThisHotkey), but perhaps using || (OR) instead of && operator?)

How slowly are you scrolling?

You can try this I suppose for indefinite scrolling:

Code: Select all

WheelUp::
If (A_PriorKey!=A_ThisHotkey)
{
Send {A}
}
return
User avatar
KilliK
Posts: 255
Joined: 10 Mar 2016, 21:19

Re: Trigger event only once with mouse wheel.

19 Jan 2017, 18:17

I used your last script, it works, but only when wheelup alternates with another button, not consecutively.

Basically, what I want to do is this:
1.scroll up fast and once, max duration 500ms
2.trigger event one time.
3.a few minutes pass without pressing anything else.
4.repeat.

the problem is with step 1, regardless of how fast i scroll, the event is triggered one or two times randomly. so i want to make sure it will only trigger one time every time I use scroll.
User avatar
Almost_there
Posts: 404
Joined: 30 Sep 2014, 10:32

Re: Trigger event only once with mouse wheel.

19 Jan 2017, 18:58

Like this (I replaced Send with Soundbeep)?

Remember - there is no way I can make the code guess the next delay for the mouse (well yes there is a way, but I don't think it will make the script behave as you want it to).

Code: Select all

#Persistent

wheelup::
	soundbeep, 4000, 50
	SetTimer, sleepHalfSecond, -500
return

wheeldown::
	soundbeep, 4200, 50
	SetTimer, sleepHalfSecond, -500
return


sleepHalfSecond:
	soundbeep, 3000, 500
Return
User avatar
Exaskryz
Posts: 2882
Joined: 17 Oct 2015, 20:28

Re: Trigger event only once with mouse wheel.

19 Jan 2017, 19:07

Oooh, I think maybe this'll work.

Code: Select all

WheelUp::
If (A_PriorKey!=A_ThisHotkey) || (A_TickCount-LastActivation > 10000)
{
LastActivation:=A_TickCount
Send {A}
}
return
If it has been greater than 10 seconds since you last activated this hotkey successfully, it'll trigger again. You said 500 milliseconds, which could be imposed here, but I'd think maybe 2000 or 3000 milliseconds will prevent any accidental activations.
User avatar
Almost_there
Posts: 404
Joined: 30 Sep 2014, 10:32

Re: Trigger event only once with mouse wheel.

20 Jan 2017, 16:38

I have an half idea of measure the wheel speed, but need op's feedback to latest posts.
User avatar
KilliK
Posts: 255
Joined: 10 Mar 2016, 21:19

Re: Trigger event only once with mouse wheel.

21 Jan 2017, 01:13

Thank you for all the help. I tried both methods, they work well, but Almost_There's was the more consistent, so I will use his for now. I put the duration to 300ms and so far, the event is triggered only once as long as I make a fast, single scrolling.
again, thanks for the help.

Almost_There, would like to see your idea for measuring the wheel speed, if you are still interested.
User avatar
Almost_there
Posts: 404
Joined: 30 Sep 2014, 10:32

Re: Trigger event only once with mouse wheel.

21 Jan 2017, 14:02

Ok - I think I got it to work.

The idea here is to measure the time between two WheelUp actions. after the third WheelUp actio, time is compared between this click and last click, and is compared to the time between last click and the click before. If the time between last two clicks is much longer (3 times here) than the time between the clicks before, then the subroutine runs.

When testing, it appear to be a problem when a human suddenly goes from fast scrolling to slow scrolling, then the sub routine will most probably run, even if your initial purpose is to continue scrolling, just slower.
To overcome this problem, you can increase the scrollTimeIncreaseFactor.

Code: Select all

Global t	; Store last value for A_TickCount.
safeSpeedAbove_Delay_ms := 100	; Disable calculation when mouse wheel speed is higher than 1/thisdelay (no unit for speed).

scrollTimeIncreaseFactor := 3	; If the time between two click exceeds 3 times the time before last two click, activate 
#Persistent

wheelup::
	SetTimer, doSomethingAtEndOfScrolling, -500	; ensures if scrolling suddenly stops (without speed decreasing) it still run the after-scrolling-routine (first intention for this timer)
	; It also make sure that the doSomethingAtEndOfScrolling routine also runs after just one or two scrolls.
	theOtherTaskIsAlreadyDone := 0	; when 0, it doesn't prevent "doSomethingAtEndOfScrolling " from running.
	soundbeep, 4000, 10
	; Makes up history for timing between 3 last click, so being able to compare.
	timeBetweenScrolls_last := timeBetweenScrolls
	timeBetweenScrolls := timeBetweenCalls()
	ToolTip, timeBetweenScrolls_last`t%timeBetweenScrolls_last%`ntimeBetweenScrolls`t%timeBetweenScrolls%
	If  (timeBetweenScrolls_last && timeBetweenScrolls) {	; Does not run the first or second time, when variable is'n set yet
		;MsgBox, kommer hit
		If ((timeBetweenScrolls > (timeBetweenScrolls_last * scrollTimeIncreaseFactor)) && ((timeBetweenScrolls_last > safeSpeedAbove_Delay_ms) || ( timeBetweenScrolls > safeSpeedAbove_Delay_ms))) {
			; Doesn't run if last delay is much longer OR delay between scroll is less than safeSpeedAbove_Delay_ms
			SetTimer, doSomethingAtEndOfScrolling, Off
			GoSub, doSomethingAtEndOfScrolling
		} Else	; delay between clicks is within limits. 
			; Updates the timer - it will run sooner, so the script shouldn't wait for the original timer that takes more than one second to start.
			; This make sense if you roll the mouse wheel fast some times.
			SetTimer, doSomethingAtEndOfScrolling, % timeBetweenScrolls_last * scrollTimeIncreaseFactor * 1.2
			; ERROR - The SetTimer doesn't truly support expressions, I need to put a percent sign before the calculation.
	} Else
		SetTimer, doSomethingAtEndOfScrolling, -500
return

/*
wheeldown::
	; put similar code here
return
*/

; if t is zero - it returns nothing.
timeBetweenCalls() {
	if !t
		t := A_TickCount
	Else
		u := A_TickCount - t
		t := A_TickCount
		Return u
}


doSomethingAtEndOfScrolling:
	t := 0	; clear timer
	If theOtherTaskIsAlreadyDone	; Prevent sub from running twice at same hotkey.
		Return
	theOtherTaskIsAlreadyDone := 1
	timeBetweenScrolls_last := 0	; when this sub runs- that means you're done scrolling for now. 
	soundbeep, 3000, 500
	ToolTip
	SetTimer, doSomethingAtEndOfScrolling, Off
Return

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: Bing [Bot], Rohwedder, Scr1pter and 249 guests