Что нового

Мышь, клавиатура Как предотвратить случайный повторный вызов функции по горячей клавише?

Oki

Продвинутый
Сообщения
452
Репутация
62
Речь идёт именно о случайном вызове в результате несвоевременного отпускания нажатой клавиши, воспринимаемой в качестве удерживаемой. Следующий скрипт, например, такой случайный вызов не предотвращает.
Код:
HotKeySet("+a", "_MyFunction")
$iCount = 0
While 1
   Sleep(10)
WEnd
Func _MyFunction()
   $iCount += 1
   ToolTip($iCount, 500, 350)
EndFunc
Более того, почему-то скрипт не реагирует на горячую клавишу вовсе, если в момент его запуска была включена русская раскладка, сразу же после запуска переключённая на английскую. А вот если в момент запуска была включена английская раскладка, то срабатывает в любой раскладке, словно игнорируя переключения. Но это, впрочем, интересный момент, но уводящий в сторону от основного вопроса: предотвращение случайных повторных срабатываний, для борьбы с которыми добавлена ещё одна строка кода; получился следующий скрипт.
Код:
HotKeySet("+a", "_MyFunction")
$iCount = 0
While 1
   Sleep(10)
WEnd
Func _MyFunction()
   Send("{a up}")
   $iCount += 1
   ToolTip($iCount, 500, 350)
EndFunc
По не вполне очевидной причине такой трюк ничего не меняет: обе проблемы остаются неразрешёнными. Что не так, и как с этим бороться?
 
Последнее редактирование:

xXx

╚{■_■}╗
Меценат
Сообщения
248
Репутация
95
Что касается первой проблемы, той что в названии темы, то можно поступить примерно так:
Код:
HotKeySet("+a", "_MyFunction")
Global $iCount
While 1
    Sleep(10)
WEnd
Func _MyFunction()
    If Not $iCount Then
        $iCount += 1
        ToolTip($iCount, 500, 350)
        Sleep(2000)
        ToolTip('')
        $iCount = 0
    EndIf
EndFunc   ;==>_MyFunction

Что касается второй вашей проблемы, то советую почитать *Это*.
 
Автор
Oki

Oki

Продвинутый
Сообщения
452
Репутация
62
можно поступить примерно так:
Так основная часть функции всё равно отрабатывает, в предложенном коде всего лишь замаскирована демонстрация этого факта. Так что это вовсе не решение. Попробую объяснить другими словами. Требуется такое решение, при котором определённый (основной) блок функции вообще не срабатывал бы более одного раза (чтобы туда не попадало выполнение), если горячая кнопка, вызывающая эту функцию, нажата и удерживается. После того, как горячая клавиша отпущена, повторный вызов должен быть доступен. Понятно, что функция сама по себе запустится в любом случае, но некий внешний её блок не должен пускать внутрь. Можно также представить для формального описания, что эта функция вызывает другую функцию, но только в разрешённом таким правилом случае.

А за ссылку на топик по поводу неосновной проблемы благодарю. Грустно, что самый активный пользователь форума между делом говорит о том, что некая проблема известна, а в справке об этом ни слова.
 
Последнее редактирование:

xXx

╚{■_■}╗
Меценат
Сообщения
248
Репутация
95
Попробую объяснить другими словами.
В следующий раз с "других" слов и начинайте объяснение, а за одно и тему назовите "другими" словами.
Еще вариант:
Код:
#include <Misc.au3>
HotKeySet('+a', '_MyFunction')

Global $iCount
While 1
    Sleep(10)
WEnd

Func _MyFunction()
    HotKeySet('+a')
    $iCount += 1
    ToolTip($iCount, 500, 350)
    While (_IsPressed('10') And _IsPressed('41'))
        Sleep(100)
    WEnd
    HotKeySet('+a', '_MyFunction')
EndFunc   ;==>_MyFunction
 
Автор
Oki

Oki

Продвинутый
Сообщения
452
Репутация
62
В следующий раз с "других" слов и начинайте объяснение, а за одно и тему назовите "другими" словами.
Такое предложение было бы уместным, если бы другие слова приводили к другой задаче, а не разжёвывали смысл ранее сказанного для тех, кто его не уловил. Мне трудно представить, как изначально сформулированное воспринято так, словно вместо невыполнения нужно замаскировать счётчик, который существовал явно для демонстрации срабатываний.
Этот вариант не перехватывает неучтённые горячие клавиши вовсе. В этом легко убедиться, активировав, например, блокнот, в который автоматически будет набираться текст из неучтённых клавиш. Правда, в определённых условиях всё же этот код, в отличие от предыдущего может быть полезным. Хотя даже в нём пришлось бы задержку аж в 100 миллисекунд значительно уменьшить, иначе часто не срабатывают даже законные по требуемым правилам повторные нажатия (не случайные, а просто быстро следующие одно за другим). Именно по этой причине такой подход (который был виден и самостоятельно), был мной отвергнут до открытия этого топика, и искался подход наподобие несработавшей строки Send("{a up}"). Вот если бы удалось заставить скрипт считать, что клавиша отпущена, пока она удерживается, задача была бы решена. Вероятно, существуют другие подходы, необязательно именно так.
 
Последнее редактирование:

xXx

╚{■_■}╗
Меценат
Сообщения
248
Репутация
95
а не разжёвывали смысл ранее сказанного для тех, кто его не уловил
такой подход (который был виден и самостоятельно), был мной отвергнут до открытия этого топика
Видимо я туп для ваших хотелок. Прошу прощения что вмешался в дискуссию.
 

IMStrelcov

CTPEJIbLLOB
Сообщения
253
Репутация
64
предотвращение случайных повторных срабатываний
Код:
#include <Misc.au3>

$iUp = 0

HotKeySet("+a", "_MyFunction")
$iCount = 0
While 1
   Sleep(10)
   If $iUp And (Not _IsPressed('41')) Then $iUp = 0
WEnd
Func _MyFunction()
   If $iUp Then Return 0
   $iUp = 1
   $iCount += 1
   ToolTip($iCount, 500, 350)
EndFunc

Или так, но тогда после нажатия клавиши нужно ждать пока вызываемая функция полностью не отработает (так себе вариант), но работает вроде с любой запущенной раскладкой.
Код:
#include <WinAPISys.au3>
#include <WinAPIvkeysConstants.au3>

Global Const $iBitMask = 0x8000
Global Const $iKeyA = 0x41
Global Const $iKeyLSHIFT = 0xA0
Global Const $iKeyRSHIFT = 0xA1
Global $iUp = 0
Global $iCount = 0
Global $iStateA, $iStateLSHIFT, $iStateRSHIFT

While 1
   Sleep(10)
   $iStateA = BitAND(_WinAPI_GetAsyncKeyState($iKeyA), $iBitMask)
   $iStateLSHIFT = BitAND(_WinAPI_GetAsyncKeyState($iKeyLSHIFT), $iBitMask)
   $iStateRSHIFT = BitAND(_WinAPI_GetAsyncKeyState($iKeyRSHIFT), $iBitMask)
   If ($iStateLSHIFT Or $iStateRSHIFT) And $iStateA Then
      If Not $iUp Then _MyFunction()
   ElseIf $iUp Then
      $iUp = 0
   EndIf
WEnd

Func _MyFunction()
   If $iUp Then Return 0
   $iUp = 1
   $iCount += 1
   ToolTip($iCount, 500, 350)
EndFunc

Ну или регистрировать горячие клавиши через WinAPi функции, пока нет времени привести такой пример.
 
Последнее редактирование:
Автор
Oki

Oki

Продвинутый
Сообщения
452
Репутация
62
Этот код работает, и вот так
Код:
#include <Misc.au3>
$iUp = 0
HotKeySet("+a", "_MyFunction")
$iCount = 0
While 1
   If Not _IsPressed('41') Then $iUp = 0
WEnd
Func _MyFunction()
   If Not $iUp Then
      $iUp = 1
      $iCount += 1
      ToolTip($iCount, 500, 350)
   EndIf
EndFunc
тоже будет работать, но проблематично вставить такой фокус в скрипт, который не просто пассивно ожидает нажатия конкретной клавиши, а выполняет что-то полезное, прерываясь именно на горячую по своей сути клавишу.
Ну или регистрировать горячие клавиши через WinAPi функции, пока нет времени привести такой пример.
А при таком подходе есть возможность зарегистрировать именно горячие клавиши, прерывающие работу скрипта, как полагается?
 
Последнее редактирование:

IMStrelcov

CTPEJIbLLOB
Сообщения
253
Репутация
64
но проблематично вставить такой фокус в скрипт, который не просто пассивно ожидает нажатия конкретной клавиши, а выполняет что-то полезное, прерываясь именно на горячую по своей сути клавишу.
Код:
#include <Misc.au3>
#include <Timers.au3>

$iUp = 0
$iCount = 0

HotKeySet("+a", "_MyFunction")
_Timer_SetTimer(0, 10, 'Check_Key_')

While 1
   Sleep(10)
WEnd

Func _MyFunction()
   If $iUp Then Return 0
   $iUp = 1
   $iCount += 1
   ToolTip($iCount, 500, 350)
EndFunc

Func Check_Key_($hWnd, $Msg, $iIDTimer, $dwTime)
   If $iUp And (Not _IsPressed('41')) Then $iUp = 0
EndFunc
 
  • Like
Реакции: Oki
Автор
Oki

Oki

Продвинутый
Сообщения
452
Репутация
62
Последнее редактирование:
Верх