1 (изменено: Narrator, 2015-07-26 09:51:08)

Тема: AHK: Неадекватное поведение AHK (или меня)

Привет, ребят. Переписываю свой AHK-скрипт на ООП, вот этот крайне важный кусок кода работает некорректно. Я пробовал во всех вариациях, до которых смог додуматься, я убил 4 часа и гуглил как мог, выручайте!


class Grabber {
    __new(){
        this.vkKey := "vk5A"
    }

    grab() {
        Send % "{" this.vkKey " down}{" this.vkKey " up}"
        ;return
    }

    start() {
        setTimer, % this.grab(), 150
        ;return
    }

    stop() {
        setTimer, % this.grab(), off
        ;return
    }
}

class Handler {
    __new() {
        this.grabber := new Grabber
        this.grabberActive := false
    }

    handle(module) {

        if (module == "Grabber") {
            if (this.grabberActive == true) {
                this.grabber.start()
                this.grabberActive := false
            } else {
                this.grabber.stop()
                this.grabberActive := true
            }
        }
    }
}

; /// Точка входа

handler := new Handler

F2::handler.handle("Grabber")

Написанный выше код нормально работает в процедурном стиле. Если из кода непонятно, то я хочу, чтобы по нажатию F2 начиналась бесконечная отправка клавиши z (vk5A), а если нажать еще раз — прекращалась.

Насколько я понял, каждая итерация цикла в setTimer дергает (ЗАЧЕМ?!) метод handle из совсем другого класса, из-за этого там меняются значение true/false и все работает криво, но может быть, я неправильно понял. Как с этим бороться? Как добиться нужного? Подскажите, пожалуйста, буду очень благодарен!

P.S. Пример рабочий, можно вставить и запустить.

2 (изменено: Alectric, 2015-07-26 09:18:44)

Re: AHK: Неадекватное поведение AHK (или меня)

Что-то тут перемудрено так все... или я чего-то не понимаю?

vkKey=vk5a

f2::
state:=!state
settimer,loop,% state ? 0 : "off"
return

loop:
Send % "{" vkKey " down}{" vkKey " up}"
return

...

Тут хендлер два раза подряд выполняется, не знаю почему:


class Grabber {
    __new(key,deley){
        this.vkKey := key
        this.Deley := deley
    }

    grab() {
        Send % "{" this.vkKey " down}{" this.vkKey " up}"
        ;return
    }

    start() {
        setTimer, % this.grab(), % this.Deley ; если убрать этот таймер то все в порядке
        ;return
    }

    stop() {
        setTimer, % this.grab(), off
        ;return
    }
}

class Handler {
    __new(key,deley) {
        this.grabber := new Grabber(key,deley)
        this.grabberActive := false
        this.dotActive := false
    }

    handle(module) {
tooltip,% module "`n" this.grabberActive
        if (module == "Grabber") {
            if (this.grabberActive == true) {
                this.grabber.start()
                this.grabberActive := false
            } else {
                this.grabber.stop()
                this.grabberActive := true
            }
        }
    }
}

; /// Точка входа

handler_1 := new Handler("vk5A",150)
handler_2 := new Handler("vk51",10)

F2::handler_1.handle("Grabber")
F3::handler_2.handle("Grabber")
Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

3 (изменено: Narrator, 2015-07-26 09:22:38)

Re: AHK: Неадекватное поведение AHK (или меня)

Alectric, Спасибо, поправил название. В том то и дело, что нужно, чтобы работало так или очень близко к этому, на процедурном то и у меня работало, я об этом говорил в шапке, так что пример неуместен

4

Re: AHK: Неадекватное поведение AHK (или меня)

Проблема с таймером, смотри код выше:

        setTimer, % this.grab(), % this.Deley ; если убрать этот таймер то все в порядке
 
Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

5 (изменено: Narrator, 2015-07-26 09:47:52)

Re: AHK: Неадекватное поведение AHK (или меня)

Alectric, да проблема не с таймером, проблема в том, что каждая его итерация дергает метод из совершенно другого класса, из-за чего все и слетает, ну я об этом в шапке написал)

6 (изменено: Alectric, 2015-07-26 11:23:22)

Re: AHK: Неадекватное поведение AHK (или меня)

Думаю что это проблема Autohotkey, ошибка или еще что-то. В общем, таймеры внутри классов не работают, да в принципе и не логично их так использовать, это же классы (в моем понимании - объекты с набором функций и индивидуальными параметрами одних и тех же переменных)... Может я и ошибаюсь, не изучал классы подробно.

; /// Точка входа

handler_1 := new Handler("vk5A",150)
handler_2 := new Handler("vk51",10)

F2::
if s:=!s
  handler_1.handle("Grabber")
else
  handler_1.stop_start("Grabber")
tooltip,% s,,0,3  ;  эта тултипка появляется несколько раз подрят от одного нажатия, как-будто скрипт перезапускается или... не знаю.
return

F3::handler_2.handle("Grabber")

return

class Grabber {
    __new(key,deley){
        this.vkKey := key
        this.Deley := deley
    }

    grab() {
        Send % "{" this.vkKey " down}{" this.vkKey " up}"
        ;return
    }

    start() {
        setTimer, % this.grab(), % this.Deley ; если убрать этот таймер то все в порядке
        ;return
    }

    stop() {
        setTimer, % this.grab(), off
        ;return
    }
}

class Handler {
    __new(key,deley) {
        this.grabber := new Grabber(key,deley)
        this.grabberActive := false
        this.dotActive := false
    }

    handle(module) {
tooltip,% module "`n" this.grabberActive
        if (module == "Grabber") {
            if (this.grabberActive == false) {
                this.grabber.start()
            } else {
                this.grabber.stop()
            }
        }
    }
    stop_start(module)
    {
tooltip,% module "`n" this.grabberActive,0,,2
        if (module == "Grabber")
        {
          this.grabberActive := !this.grabberActive
        }
    }
}

Вот что дает одно нажатие F2:

007: if s:=!s  
008: handler_1.handle("Grabber")  
048: ToolTip,module "" this.grabberActive (0.03)
049: if (module == "Grabber")  
050: if (this.grabberActive == false)  
051: this.grabber.start()  
030: SetTimer,this.grab(),this.Deley
025: Send,"{" this.vkKey " down}{" this.vkKey " up}" (0.11)
027: }
032: }
052: }
055: }
056: }
011: ToolTip,s,,0,3
012: Return (0.16)
007: if s:=!s  
010: handler_1.stop_start("Grabber")  
059: ToolTip,module "" this.grabberActive,0,,2
060: if (module == "Grabber")  
062: this.grabberActive := !this.grabberActive  
063: }
064: }
011: ToolTip,s,,0,3 (0.03)
012: Return (0.13)
007: if s:=!s  
008: handler_1.handle("Grabber")  
048: ToolTip,module "" this.grabberActive
049: if (module == "Grabber")  
050: if (this.grabberActive == false)  
053: this.grabber.stop()  
035: SetTimer,this.grab(),off
025: Send,"{" this.vkKey " down}{" this.vkKey " up}" (0.03)
027: }
037: }
054: }
055: }
056: }
011: ToolTip,s,,0,3
012: Return (0.95)

Т.е. таймером является метка самой клавиши F2.

Даже если взять самый первый пример:

class Grabber {
    __new(){
        this.vkKey := "vk5A"
    }

    grab() {
        Send % "{" this.vkKey " down}{" this.vkKey " up}"
        ;return
    }

    start() {
        setTimer, % this.grab(), 150
        ;return
    }

    stop() {
        setTimer, % this.grab(), off
        ;return
    }
}

class Handler {
    __new() {
        this.grabber := new Grabber
        this.grabberActive := false
    }

    handle(module) {

        if (module == "Grabber") {
            if (this.grabberActive == true) {
                this.grabber.start()
                this.grabberActive := false
            } else {
;                this.grabber.stop()
                this.grabberActive := true
            }
        }
    }
}

; /// Точка входа

handler := new Handler

F2::
tooltip,% a_tickcount
handler.handle("Grabber")
return

Первое нажатие ничего не дает кроме тултипки, следующее запускает таймер вида:

settimer,f2,150

F2::
tooltip,% a_tickcount
return
Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

7 (изменено: shiz, 2015-07-26 11:04:54)

Re: AHK: Неадекватное поведение AHK (или меня)

        setTimer, % this.grab(), 150

Ничего не запускал, но:
1) для начала, меня смущают круглые скобки: по таймеру должен вызываться метод grab или этот метод должен быть вызван однократно при создании таймера?!
2) если по таймеру должен вызываться метод grab, то не уверен, что в момент срабатывания таймера this будет разрешаться в объект, в методе start которого создан таймер.

По крайней мере в документации:

SetTimer [, Label, Period|On|Off|Delete, Priority]Parameters

Label
<...>
[v1.1.20+]: If not a valid label name, this parameter can be the name of a function, or a single variable reference containing a function object. For example, SetTimer %funcobj%, 1000 or SetTimer % funcobj, 1000. Other expressions which return objects are currently unsupported.

Забыл пароль и потерял e-mail.

8 (изменено: Alectric, 2015-07-26 11:02:58)

Re: AHK: Неадекватное поведение AHK (или меня)

Так работает, но подозреваю что не это требовалось:

; /// Точка входа

handler_1 := new Handler("vk5A",150)
handler_2 := new Handler("vk51",10)

F2::
if s:=!s
  settimer,send1,150
else
  settimer,send1,off
return

F3::
if s2:=!s2
  settimer,send2,10
else
  settimer,send2,off
return

send1:
handler_1.handle("Grabber")
return

send2:
handler_2.handle("Grabber")
return


class Handler {
    __new(key,deley) {
        this.vkKey := key
        this.Deley := deley
    }

    handle(module) {
        if (module == "Grabber") {
            Send % "{" this.vkKey " down}{" this.vkKey " up}"
        }
    }
}
Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

9

Re: AHK: Неадекватное поведение AHK (или меня)

Дополнил рассуждения.

Win 10 x64
AHK v1.1.33.02
                       Справка тебе в помощь.

10

Re: AHK: Неадекватное поведение AHK (или меня)

К сожалению, да, AHK в такой ситуации ведет себя неадекватно и пришлось запилить небольшой костыль. Если есть желание — можно развить тему, предложить свои варианты, я могу показать то, как я это обошел, если нет — тему можно закрывать. Благодарю Alectric за внимание и ставлю плюс ему в репу.

11

Re: AHK: Неадекватное поведение AHK (или меня)

В такой ситуации

        setTimer, % this.grab(), 150

AHK не в чем винить — он делает точно то, что ему приказано: вызывает метод grab и создаёт таймер с меткой или функцией, имя которой (т.е. строку) возвращает grab (если бы возвращал).

Пробовал сделать

        setTimer, % ObjBindMethod(this, "grab"), 150

но не получилось. Вот тут, возможно AHK и не справляется, но более вероятно, что я не всё понимаю.

Забыл пароль и потерял e-mail.

12

Re: AHK: Неадекватное поведение AHK (или меня)

shiz, Как это не в чем? Таймер то создает, функция работает, только каждая итерация таймера тянет за собой всех предков вплоть до кнопки. В процедурном программировании такого нет, следовательно, это неестественно и должно работать иначе. Получается, косяк AHK, поправьте если не прав.

13

Re: AHK: Неадекватное поведение AHK (или меня)

Распишу

        setTimer, % this.grab(), 150

подробнее:

       LabelOrFunctionName := this.grab()
       setTimer, % LabelOrFunctionName, 150
Забыл пароль и потерял e-mail.

14 (изменено: Stremin, 2015-09-02 14:05:46)

Re: AHK: Неадекватное поведение AHK (или меня)

Дополню тему, может кому понадобится пример использования таймеров в классе. Для того, чтобы скрипт из 1го сообщения работал, как предполагал Narrator, следует изменить методы start и stop таким образом:


    start() {
        timer := this.grab.bind(this)
        this.timer := timer
        setTimer, %timer%, 150
        ;return
    }

    stop() {
        timer := this.timer
        this.timer := ""
        setTimer, %timer%, delete
        ;return
    }