1 (изменено: serzh82saratov, 2018-07-27 22:29:19)

Тема: AHK: GetKeyState и Wheel(Key)

Если запустить скрипт, и нажимать 1, то ожидаемо в ToolTip будет 0. Но если "крутнуть" 1 раз WheelUp, то после этого по единице будет всегда 1, почему?


#SingleInstance, Force
#NoEnv 

#InputLevel, 100

#If Func()
WheelUp::Return
#If

Func() {
 	ToolTip % GetKeyState("WheelUp", "P")
	Return 1
}

1::SendInput {WheelUp}

И почему нет блокировки, если WheelUp::Return, а по Func всегда правда. То есть по клавише "1" у меня всегда прокручивает, хотя есть тултип.

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.29.01 (Unicode 32-bit).

2 (изменено: stealzy, 2018-07-27 22:16:03)

Re: AHK: GetKeyState и Wheel(Key)

Очень странно применять GetKeyState к колесику, не находите?
Если подумать, команда всегда должна возвращать false при передаче первым аргументом WheelUp/Down.

3

Re: AHK: GetKeyState и Wheel(Key)

Нахожу.
Но почему поведение GetKeyState меняется.

если "крутнуть" 1 раз WheelUp, то после этого по единице будет всегда 1

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.29.01 (Unicode 32-bit).

4

Re: AHK: GetKeyState и Wheel(Key)

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

5

Re: AHK: GetKeyState и Wheel(Key)

Не понимаю как это объясняет изменение поведения.

И почему нет блокировки

Получается #If для примера не требуется, и "блокировку можно починить", если InputLevel указывать ниже WheelUp.


WheelUp::ToolTip % GetKeyState("WheelUp", "P")
#InputLevel, 100
1::SendInput {WheelUp}
По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.29.01 (Unicode 32-bit).

6 (изменено: serzh82saratov, 2018-07-27 23:06:43)

Re: AHK: GetKeyState и Wheel(Key)

stealzy пишет:

Ну так вы же указали опцию "P" - физическое нажатие. Нажатие из скрипта таким не является.

Если запустить скрипт, и нажимать 1, то ожидаемо в ToolTip будет 0. Но если "крутнуть" 1 раз WheelUp, то после этого по единице будет всегда 1

Так я и говорю, что при нажатии "1" после прокрутки, почему всегда 1 становится, если хоткей "1" эмулирует через SendInput {WheelUp}, но до того как тронули колёсико показывает ноль.

Вообще засовывать в #If функцию, выполняющую какое-то действие помимо возврата, плохая идея.

Я же в 5 посте привёл пример без #If.
И идея плоха до ограничения 300мс, написано в #IfTimeout.

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.29.01 (Unicode 32-bit).

7

Re: AHK: GetKeyState и Wheel(Key)

Это не физическое нажатие, с чего бы там 1 будет?

Так я и говорю что там ожидаемо ноль.

Интерпретатор не получил сообщение о физическом отжатии

В случае с колёсиком события отжатия может вообще не существовать.

Логически вы жмете или физически - какая к черту разница?

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

Надеюсь донес мысль.

Нет, а я.

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.29.01 (Unicode 32-bit).

8 (изменено: stealzy, 2018-07-28 00:00:45)

Re: AHK: GetKeyState и Wheel(Key)

serzh82saratov пишет:

события отжатия может вообще не существовать.

О чем и речь, ситуацию что кто-то будет применять GetKeyState к колесику просто не предусмотрели.
А 0 вначале естественен - после опроса устройств выяснилось что WheelUp "не зажат" .

P.S.
Для получения логического состояния полагаю переменные не используются, поэтому GetKeyState("WheelUp") всегда возвращает 0, как и положено.
Очень любопытно зачем вы применили эту команду к колесу, тем более с опцией "P"? В этом есть некий смысл?

9

Re: AHK: GetKeyState и Wheel(Key)

Значит это баг, а если бы не предусмотрено было бы вообще, то и поведение GetKeyState не менялось бы.
Надо писать багрепорт. Да и лечится это должно просто, во всяком случае в хоткеях на хуке, в LowLevelMouseProc есть флаг про это.

Кстати, зачем вам это?

Знать эмулировано нажатие, или нет.

А 0 вначале естественен - после опроса устройств выяснилось что WheelUp "не зажат

Тогда потом откуда единица вылазит, если всё равно кто нажал, нет события, и вообще это не предусмотрено.

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.29.01 (Unicode 32-bit).

10 (изменено: stealzy, 2018-07-28 00:33:33)

Re: AHK: GetKeyState и Wheel(Key)

Да, это баг, колесо надо обрабатывать отдельно — возвращать всегда 0 .
В исправлении этого бага нет абсолютно никакого смысла - GetKeyState нельзя применять к колесу.
GetKeyState - метод, который берет состояние, а у колеса нет состояний, значит вам нужен метод, который будет вызываться по событию (а-ля хук).
evilC должен знать ответ на этот вопрос.

serzh82saratov пишет:

Тогда потом откуда единица вылазит, если всё равно кто нажал, нет события

Как нет события??? Вы же нажали WheelUp - событие есть и оно записывается. А вот о том, что {WheelUp Up} не существует, AHK не в курсе.
А для взятия логических состояний используется другой метод - AHK не записывает внутри себя состояния.

11 (изменено: serzh82saratov, 2018-07-28 00:57:35)

Re: AHK: GetKeyState и Wheel(Key)

Да, это баг, колесо надо обрабатывать отдельно — возвращать всегда 0 .

Ага, хотя бы так для начала.

AHK не записывает внутри себя эту информацию.

Но если обработка идёт внутри хука, то ничего не стоит изменить её на ноль в случае эмулированного нажатия.


#SingleInstance Force
#NoEnv
#Persistent
CoordMode, ToolTip 

MouseHook.Set() 

esc::ExitApp

class MouseHook
{
   Set()  {
      if !this.hook  {
         this.hook := this.SetMouseHook()
         OnExit( this.OnExit := ObjBindMethod(this, "Del") )
      }
   }
   
   Del()  {
      if this.hook  {
         this.SetMouseHook(this.hook)
         this.hook := ""
         OnExit(this.OnExit, 0)
      }
   }
   
   SetMouseHook(hHook := "")  {
      if hHook
         DllCall("UnhookWindowsHookEx", Ptr, hHook)
      else
         Return hHook := DllCall("SetWindowsHookEx", Int, WH_MOUSE_LL := 14
                                                   , Int, RegisterCallback("LowLevelMouseProc", "Fast")
                                                   , Ptr, DllCall("GetModuleHandle", UInt, 0, Ptr)
                                                   , UInt, 0, Ptr)
   }
}

LowLevelMouseProc(nCode, wParam, lParam)  {
   static oMem := [], lpData, size := VarSetCapacity(lpData, 16 + A_PtrSize*2, 0)
	If (wParam != 0x20A)  ;	WM_MOUSEWHEEL
		Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, Ptr, wParam, Ptr, lParam)
	DllCall("RtlMoveMemory", Ptr, &lpData, Ptr, lParam, Ptr, size)
	oMem.Push([wParam, &lpData])
	timer := Func("EventHandling").Bind(oMem)  ; во избежание фризов мыши обработка событий должна
	SetTimer, % timer, -10           ; происходить обязательно по таймеру, а не в теле этой функции
	Return DllCall("CallNextHookEx", Ptr, 0, Int, nCode, Ptr, wParam, Ptr, lParam)
}

EventHandling(oMem)  {  
   while event := oMem.RemoveAt(1)  {
      ext       := NumGet(event[2] + 10, "Short")
      flags     := NumGet(event[2] + 12, "UInt") 
      INJECTED  := flags & 1
      ToolTip % (ext = 120 ? "WheelUp" : "WheelDown") "`n" (INJECTED ? "Emulated" : "Physical"), 0, 0, 20
   } 
}

1::SendInput {WheelUp}
2::SendInput {WheelDown}

Конечно понятно, что если через час вызвать GetKeyState исходя из переменной в этой функции, то он вернёт то что было час назад, но если GetKeyState применимо к колёсику изначально не имеет смысла, то это может иметь смысл сразу после посыла колёсика. И как раз с помощью #If может быть однозначно определено как именно в последний раз послано колёсико.

А для взятия логических состояний используется другой метод

Известных методов и так несколько, и без evilC, разговор про то, что это можно сделать встроенным, тем более на фоне бесполезности и невнятности существующего GetKeyState в отношении Wheel(Key).

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.29.01 (Unicode 32-bit).

12

Re: AHK: GetKeyState и Wheel(Key)

stealzy пишет:

А вот о том, что {WheelUp Up} не существует, AHK не в курсе.

Почему не в курсе?
У WheelUp и WheelDown нельзя оаределить  состояние, так как при прокручивании посылается только down событие.

13

Re: AHK: GetKeyState и Wheel(Key)

У меня не возвращает:

f11::msgbox % GetKeyState("WheelUp", "P")

14 (изменено: Malcev, 2018-07-28 03:46:51)

Re: AHK: GetKeyState и Wheel(Key)

Так в чем собственно проблема?
Если не существует WheelUp Up события, то смысл обсуждать GetKeyState?
Так возвращает единицу, так как отправляется down, а up не существует.

WheelUp::msgbox % GetKeyState("WheelUp", "P")

Точно так же будет возвращать единицу, если перед нажатием f11 покрутить колесико:

#InstallmouseHook
f11:: msgbox % GetKeyState("WheelUp", "P")

15 (изменено: serzh82saratov, 2018-07-28 11:54:56)

Re: AHK: GetKeyState и Wheel(Key)

Тема про то, что я предлагаю написать в багрепорт о разном поведении GetKeyState применимо к Wheel, до и после нажатия.
И исправить это не на всегда ноль, а всегда ноль для опции L.
А в опции P сохранять флаг физического или нефизического нажатия.
Чтобы в момент нажатия можно было просто определить - физически отправлено или нет.
С клавишами это удобно:


2::ToolTip % GetKeyState("2", "P")
#InputLevel, 100
3::SendInput {2}

Хочется чтобы так же работало и с колёсиком:


WheelUp::ToolTip % GetKeyState("WheelUp", "P")
#InputLevel, 100
3::SendInput {WheelUp}
По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.29.01 (Unicode 32-bit).

16

Re: AHK: GetKeyState и Wheel(Key)

Malcev пишет:

Так возвращает единицу, так как отправляется down

Если нажать на 3, тоже отправляется down, но возвращается ноль.

WheelUp::ToolTip % GetKeyState("WheelUp", "P")
#InputLevel, 100
3::SendInput {WheelUp}
По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.29.01 (Unicode 32-bit).

17

Re: AHK: GetKeyState и Wheel(Key)

Изменить поведение на хоть сколько нибудь полезное, а логике оно противоречит и сейчас.

ради своего удобства/уменьшения кода в вашем скрипте?

Я за общее благо.

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.29.01 (Unicode 32-bit).

18 (изменено: stealzy, 2018-07-28 14:05:12)

Re: AHK: GetKeyState и Wheel(Key)

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

19

Re: AHK: GetKeyState и Wheel(Key)

Ну если так сделать, оно никому не помешает. А вместо гадания как это воспримется, я написал в багрепорт (так как разное поведение это всё таки ошибка), и заодно внёс предложение.

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.29.01 (Unicode 32-bit).

20

Re: AHK: GetKeyState и Wheel(Key)

stealzy пишет:

А поведение, которое вы описали, это по сути совершенно другая команда.

Просто это можно будет использовать только в одном случае, посмотрите оба кода в 20 посте, если починить как я предлагаю, то будет одинаково понятное и логичное поведение GetKeyState для всех кнопок, а то что есть сейчас ни к селу ни к городу.

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.29.01 (Unicode 32-bit).

21

Re: AHK: GetKeyState и Wheel(Key)

serzh82saratov, понял, что ты имеешь в виду.
А почему SendInput?
У меня при нажатии 3 ничего не происходит - тултипа нету.

WheelUp::ToolTip % GetKeyState("WheelUp", "P")
#InputLevel, 100
3::SendInput {WheelUp}

22

Re: AHK: GetKeyState и Wheel(Key)

Странно, может у тебя почему то пустоту возвращает.

ToolTip % GetKeyState("WheelUp", "P") "`nGetKeyState" 
По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.29.01 (Unicode 32-bit).

23

Re: AHK: GetKeyState и Wheel(Key)

Malcev пишет:

А почему SendInput?

Не знаю, работает, надо же как то послать эмуляцию.

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.29.01 (Unicode 32-bit).

24

Re: AHK: GetKeyState и Wheel(Key)

Malcev пишет:

serzh82saratov, понял, что ты имеешь в виду.

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

По вопросам возмездной помощи пишите письма
E-Mail: serzh82saratov@mail.ru
OS: Win7x64, AutoHotkey_L v1.1.29.01 (Unicode 32-bit).

25

Re: AHK: GetKeyState и Wheel(Key)

Я думаю поймет.
Но у меня такой код не работает:

WheelUp::msgbox
#InputLevel, 100
3::SendInput {WheelUp}

Если Sendinput заменить на send то работает.