Почему выражение: Если (A: =! A) оценивать по-разному при каждом нажатии горячей клавиши? - PullRequest
0 голосов
/ 07 июня 2019

В скрипте Autohotkey, когда пользователь нажимает клавишу CapsLock , должен появиться SplashText , указывающий, что он включен или выключен, когда он выключен, проблема в том, что не о коде, который заставляет его работать, а о том, насколько проще это сделать.

Существуют различные способы сделать это, некоторые требуют около 25 строк, некоторые используют SetTimer и GetKeyState внутренние функции и несколько циклов, чтобы запустить его, некоторые всего около пяти и петель нет.

Простейшее:

#SingleInstance Force
SetCapsLockState, Off


~CapsLock::
If (Tog:=!Tog)
SplashTextOn ,350 ,35 , Wanted !, [CapsLock] Activated.
else
SplashTextOff

return

Как: If (Tog: =! Tog) так легко запустить этот код? Tog - это просто не инициированная переменная, и каждый раз, когда нажимается CapsLock , она непрерывно меняет свое значение с 1 на 0

Кажется, он действует как флаг в коде? что мне не хватает в этой строке:

If (Tog:=!Tog)

Что заставляет его оценивать по-разному каждый раз?

Ниже приведен другой подход с A = 0 , работающим в качестве переключателя, я сделал это, и он не совсем такой простой, как хотелось бы, но он делает работа.

Более длинный код:

#SingleInstance Force 
SetCapsLockState, Off

~CapsLock::

    If (A = 0) 
    {
    SplashTextOn ,350 ,35 , Wanted !, [CapsLock] Activated.
    A=1
        }else
        {
        SplashTextOff
        A=0
        }

return 

Самый длинный код:

Этот последний получает тот же результат, но проверяет фактическое физическое состояние ключа. Он не будет полагаться на SetCapsLockState, Off в верхней части скрипта, чтобы убедиться, что коммутатор выполнит остальную часть работа в одну строчку как более простая.

#SingleInstance Force
#Persistent

SetTimer, StateCapsLockON_Timer, 100
Return

~CapsLock::

StateCapsLockON_Timer
    If GetKeyState("CapsLock", "T")
    {
    SetTimer, StateCapsLockOFF_Timer, 100
    SplashTextOn ,350 ,35 , Wanted !, [CapsLock] Activated.
    SetTimer, StateCapsLockON_Timer, Off
    }
 Return

StateCapsLockOFF_Timer:
    If !GetKeyState("CapsLock", "T")
    {
    SetTimer, StateCapsLockOFF_Timer, Off
    SplashTextOff
    SetTimer, StateCapsLockON_Timer, On
    }
Return

Есть хорошие идеи о том, как If (Tog: =! Tog) работает в простейшем из этих трех примеров?

Ответы [ 2 ]

1 голос
/ 07 июня 2019

Я получил это сейчас, проверьте логическое - не по этой ссылке:

https://lexikos.github.io/v2/docs/Variables.htm

Если операнд (в данном случае Tog ) пуст или равен 0, результат применения логического not (или ! Tog ) равен 1, что означает «истина». В противном случае результат равен 0 (ложь)

if (Tog = 0)
  Tog = 1

даст тот же результат, что и:

If Tog:=!Tog

Поскольку операция выполнялась до того, как Если даже проверил измененное значение, , если не просто сравнивал данные, операция происходила до , если поскольку значения в скобках не только читаются, но и изменяются, а переменная переопределяется.

(выражение) Любое подвыражение, заключенное в скобки. Например, (3 + 2) * 2 заставляет 3 + 2 быть оцененными первыми.

0 голосов
/ 07 июня 2019

Ключевым отличием является использование оператора присваивания := в отличие от оператора сравнения =. Поскольку, как вы видели, вы можете оценивать выражения в операторе if, вы можете фактически включить оба оператора в один оператор if. Вот пример:

f1::
If (( test := 3+2 ) = 5 )
    MsgBox
Return

Здесь «тесту» сначала присваивается сумма 3 + 2, а затем сравнивается с 5. Таким образом, ключ заключается в том, что операторы if позволяют выполнять назначения и что назначения выполняются в первую очередь, то есть до того, как что-либо сравнивается и оценивается как истинное или ложное.

Если нет оператора сравнения (=, <,>, <=,> =), как в случае с вашим переключателем, он просто оценивает, является ли переменная истинной или ложной. Если переменная пуста, 0 или false, она оценивается как false; все остальное верно, даже строка «ложь».


Теперь для забавы. На самом деле мы можем сократить ваш код до одной строки, если мы используем Progress с опцией "zh0".
~CapsLock::Progress , % ( Tog := !Tog ) ? "zh0 w350 h35" : "Off" ,, [CapsLock] Activated. , Wanted !

К сожалению, это невозможно с SplashText, поскольку на самом деле это две отдельные команды. Но плюс в том, что Progress на самом деле имеет гораздо больше доступных вариантов, так что вы можете изменить размер и цвет шрифта и т. Д.

...