Саша Черных
Саша Черных

Reputation: 2813

Using Loop multiple times

1. Briefly

I don't understand, how I can use cycles from Loop multiple times without ending script.


2. Settings

I have a file SashaAutoScrolling.ahk, it content:

; First loop, Speed 1
#+1::
Loop
{
    Send {WheelDown}
    Sleep 3000
}

; Second loop, Speed 2
#+2::
Loop
{
    Send {WheelDown}
    Sleep 600
}

; Third loop, Speed 3
#+3::
Loop
{
    Send {WheelDown}
    Sleep 100
}

; Fourth loop, Speed Up
#+0::
Loop
{
    Send {WheelUp}
    Sleep 600
}

; Loop pause
; http://autohotkey.com/board/topic/95308-endless-loop-with-hotkey-pause/?p=600526
#p::Pause

; Exit script
#esc::ExitApp

3. Steps to reproduce

I open any pdf file in any PDF-viewer. I switch between «speeds»:


4. Actual behavior

Actual

If I run Shift+Super+3 and Shift+Super+0 first time

    I can successful switch between «speeds».

If I run Shift+Super+3 and Shift+Super+0 second and next times,

    I can't switch between «speeds».


5. Expected behavior

Successful switch between «speeds» unlimited number of times.


6. Not helped

  1. Googling, searching in Stack Overflow and AutoHotkey forum.

7. Do not offer

  1. Please, do not offer use third-party programs. Adobe Reader free version works as expected, but I can't read, use this program , for example, djvu or doc books.
  2. Please, do not offer use built-in mouse auto scrolling. It uncomfortable, because is problematic quick choose exact comfortable «speed» for reading.

Upvotes: 0

Views: 819

Answers (3)

Oleg
Oleg

Reputation: 6314

Your code doesn't work because by default there is only one thread per hotkey. When you do:

Loop
{
    Send {WheelDown}
    Sleep 100
}

You never return from this one thread so when you call it second time the hotkey will not fire and your program will continue looping in the current thread.

Jim U solved it by calling #MaxThreadsPerHotkey 2, this wouldn't have made your code work though because you don't return from your hotkey threads at all, Jim U doesn't return from the first thread only so 2 threads is enough for his solutoin to work.

An alternative solution is to use timers, the following will change the scrolling speed immediately, doesn't need any special directives and doesn't rely on Autohotkeys unique threading model.

#+1::callSetTimer(3000)
#+2::callSetTimer(600)
#+3::callSetTimer(100)
#+0::callSetTimer(600, "WheelUp")
Esc::SetTimer, scrollTimer, Off

callSetTimer(interval, key := "WheelDown") {
    global currKey := key
    SetTimer, scrollTimer, %interval%

    scrollTimer:
        send, {%currKey%}
    return
}

Upvotes: 0

Jim U
Jim U

Reputation: 3366

This code scrolls current window with simulated mouse wheel scrolls

Shift+Win+1, Shift+Win+2, etc... starts scrolling. If already scrolling, just updates sleep interval. esc exits

; globals:
;   g_running : true while loop is active
;   g_sleep   : milliseconds to sleep between sending input event
;   g_key     : key to simulate


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; HOTKEY DEFINITIONS

#MaxThreadsPerHotkey 2

#+1:: scrollit(3000)
#+2:: scrollit(600)
#+3:: scrollit(300)
#+0:: scrollit(600,"WheelUp")

#MaxThreadsPerHotkey 1

Esc:: abort()


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; HELPER FUNCTIONS

; send wheeldown every _delay_ microseconds
; if called while loop is already active, just update delay and exit
;
scrollit(sleep, key="WheelDown")
{
  global g_running
  global g_sleep := sleep
  global g_key   := key

  if g_running
    return

  g_running := true

  while (g_running)
  {
    Send {%g_key%}
    Sleep g_sleep
  }
}



abort()
{
  global g_running := false
}

Upvotes: 1

Jim U
Jim U

Reputation: 3366

Scrolls current window by simulating mouse wheel scroll when Shift+Win+1, Shift+Win+2, etc. pressed. esc exits loop

#+1:: scrollit(3000)
#+2:: scrollit(600)
#+3:: scrollit(300)
Esc:: abort()

scrollit(delay)
{
  global abort := false
  while (!abort)
  {
    Send {WheelDown}
    Sleep delay
  }
}


abort()
{
  global abort := true
}

Upvotes: 1

Related Questions