1 (изменено: sergeant.coolagin, 2012-06-30 20:08:44)

Тема: AHK: Эмуляция мыши при помощи клавиатуры

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Global Variabless ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

HatDelay = 10 ; Время таймера


XSensitivity := 5 ; Начальная скорость передвижения мыши по горизонтали.
YSensitivity := 5 ; Начальная скорость передвижения мыши по вертикали.
XAcceleration := 3 ; Ускорение мыши по горизонтали. Чем больше значение, тем быстрее будет ускорение мыши.
YAcceleration := 3 ; Ускорение мыши по вертикали. Чем больше значение, тем быстрее будет ускорение мыши.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Body ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

SetTimer, KeyMouse, %HatDelay%

KeyMouse:
{
    GetKeyState, AState, A
    GetKeyState, WState, W
    GetKeyState, SState, S
    GetKeyState, DState, D

    if (AState = U) && (WState = U) && (SState = U) && (DState = U)
    {
    XSensitivity2 := XSensitivity ; Скорость передвижения мыши по горизонтали.
    YSensitivity2 := YSensitivity ; Скорость передвижения мыши по вертикали.
    }
    
    if DState = D ; Если нажать кнопку
    {
    XAxis := XSensitivity2
    }

    if SState = D ;  Если нажать кнопку
    {
    YAxis := YSensitivity2
    }

    if AState = D ;  Если нажать кнопку
    {
    XAxis := -XSensitivity2
    }

    if WState = D ; Если нажать кнопку
    {
    YAxis := -YSensitivity2
    }

    if (AState = D || WState = D || SState = D || DState = D) ; Проверка состояния клавиш
    {

    DllCall("mouse_event", UInt, 0x1
                              , Int, XAxis
                              , Int, YAxis
                              , UInt, 0
                              , Int, 0)

    XSensitivity2 += %XAcceleration%
    YSensitivity2 += %YAcceleration%

    }

}
Return

Joy25::
{
}
Return

Решил написать простенький эмулятор мыши с ускорением. Не работает он. Я не могу найти свою ошибку. Она где-то здесь:

if (AState = U) && (WState = U) && (SState = U) && (DState = U)
    {
    XSensitivity2 := XSensitivity ; Скорость передвижения мыши по горизонтали.
    YSensitivity2 := YSensitivity ; Скорость передвижения мыши по вертикали.
    }

и здесь:

if (AState = D || WState = D || SState = D || DState = D) ; Проверка состояния клавиш
    {

    DllCall("mouse_event", UInt, 0x1
                              , Int, XAxis
                              , Int, YAxis
                              , UInt, 0
                              , Int, 0)

    XSensitivity2 += %XAcceleration%
    YSensitivity2 += %YAcceleration%

    }

Стоит убрать

if (AState = D || WState = D || SState = D || DState = D)

и эмулятор начинает работать.

Что-то не так с проверкой состояния клавиш. Подскажите, плз, в чем проблема?
Каждую строчку по 10 раз перечитал, не хочет работать

GetKeyState работает нормально.
if по отдельности тоже работает, например:

if AState = D ;  Если нажать кнопку
    {
    XAxis := -XSensitivity2
    }

а вот это:

if AState = D && SState = D ;  Если нажать кнопку
    {
    XAxis := -XSensitivity2
    }

уже работать не будет.
И вроде должно, не?

2 (изменено: creature.ws, 2012-06-30 20:26:17)

Re: AHK: Эмуляция мыши при помощи клавиатуры

GetKeyState, AState, A

В AState — строка.

If (AState = D)

Сравнение  содержимого переменной AState c содержимым переменной D

if (AState = "D" || WState = "D" || SState = "D" || DState = "D")

Сравнение  содержимого переменной AState cо строкой состоящей из символа D

Использование таймера для проверки состояний клавиш — этот подход действительно оправдан?

3

Re: AHK: Эмуляция мыши при помощи клавиатуры

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Global Variabless ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

HatDelay = 10 ; Время таймера


XSensitivity := 0 ; Начальная скорость передвижения мыши по горизонтали.
YSensitivity := 0 ; Начальная скорость передвижения мыши по вертикали.
XAcceleration := 3 ; Ускорение мыши по горизонтали. Чем больше значение, тем быстрее будет ускорение мыши.
YAcceleration := 3 ; Ускорение мыши по вертикали. Чем больше значение, тем быстрее будет ускорение мыши.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Body ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;; Hat freelook ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



SetTimer, KeyMouse, %HatDelay%

KeyMouse:
{
    GetKeyState, AState, A
    GetKeyState, SState, S
    GetKeyState, DState, D
    GetKeyState, WState, W

    if (AState = "U") && (SState = "U") && (DState = "U") && (WState = "U")
    {
    XSensitivity := 0 ; Скорость передвижения мыши по горизонтали.
    YSensitivity := 0 ; Скорость передвижения мыши по вертикали.
    }
    
    if DState = D ; Если нажать кнопку
    {
    XSensitivity += %XAcceleration%
    }

    if SState = D ;  Если нажать кнопку
    {
    YSensitivity += %XAcceleration%
    }

    if AState = D ;  Если нажать кнопку
    {
    XSensitivity += -%XAcceleration%
    }

    if WState = D ;  Если нажать кнопку
    {
    YSensitivity += -%XAcceleration%
    }

    

    if (AState = "D" || SState = "D" || DState = "D" || WState = "D") ; Проверка состояния клавиш
    {
    DllCall("mouse_event", UInt, 0x1
                              , Int, XSensitivity
                              , Int, YSensitivity
                              , UInt, 0
                              , Int, 0)
    
    }

}
Return

Joy25::
{
}
Return

Спасибо за подсказку. Вот так работает правильно.
Правильно выставил кавычки:

if (AState = "D" || SState = "D" || DState = "D" || WState = "D")

А тут правильно выставил кавычки и скобки:

if (AState = "U") && (SState = "U") && (DState = "U") && (WState = "U")
creature.ws пишет:

Использование таймера для проверки состояний клавиш — этот подход действительно оправдан?

Есть идея получше?
Можно использовать LOOP и делать это по хоткею, например:

W::
{

LOOP
{
DllCall("mouse_event", UInt, 0x1
                              , Int, -5
                              , Int, 0
                              , UInt, 0
                              , Int, 0)

GetKeyState, Wstate, W, P
if state = U
break
}

}
Return

Но таймер, по-моему более стабильный. Есть еще способы? Расскажите, мне будет интересно почитать.

Еще есть такая проблема с таймером, что нужен какой-то хоткей, чтобы программа нормально работала. Т.е. после таймера должно быть хотя бы:

Joy25::
{
}
Return

Иначе программа сразу после запуска просто закончится и закроется.

К примеру, конкретно вот так программа работать не будет:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Global Variabless ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

HatDelay = 10 ; Время таймера


XSensitivity := 0 ; Начальная скорость передвижения мыши по горизонтали.
YSensitivity := 0 ; Начальная скорость передвижения мыши по вертикали.
XAcceleration := 3 ; Ускорение мыши по горизонтали. Чем больше значение, тем быстрее будет ускорение мыши.
YAcceleration := 3 ; Ускорение мыши по вертикали. Чем больше значение, тем быстрее будет ускорение мыши.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Body ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;; Hat freelook ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



SetTimer, KeyMouse, %HatDelay%

KeyMouse:
{
    GetKeyState, AState, A
    GetKeyState, SState, S
    GetKeyState, DState, D
    GetKeyState, WState, W

    if (AState = "U") && (SState = "U") && (DState = "U") && (WState = "U")
    {
    XSensitivity := 0 ; Скорость передвижения мыши по горизонтали.
    YSensitivity := 0 ; Скорость передвижения мыши по вертикали.
    }
    
    if DState = D ; Если нажать кнопку
    {
    XSensitivity += %XAcceleration%
    }

    if SState = D ;  Если нажать кнопку
    {
    YSensitivity += %XAcceleration%
    }

    if AState = D ;  Если нажать кнопку
    {
    XSensitivity += -%XAcceleration%
    }

    if WState = D ;  Если нажать кнопку
    {
    YSensitivity += -%XAcceleration%
    }

    

    if (AState = "D" || SState = "D" || DState = "D" || WState = "D") ; Проверка состояния клавиш
    {
    DllCall("mouse_event", UInt, 0x1
                              , Int, XSensitivity
                              , Int, YSensitivity
                              , UInt, 0
                              , Int, 0)
    
    }

}
Return

А вот так уже будет:

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Global Variabless ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

HatDelay = 10 ; Время таймера


XSensitivity := 0 ; Начальная скорость передвижения мыши по горизонтали.
YSensitivity := 0 ; Начальная скорость передвижения мыши по вертикали.
XAcceleration := 3 ; Ускорение мыши по горизонтали. Чем больше значение, тем быстрее будет ускорение мыши.
YAcceleration := 3 ; Ускорение мыши по вертикали. Чем больше значение, тем быстрее будет ускорение мыши.

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;; Body ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;


;;;; Hat freelook ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



SetTimer, KeyMouse, %HatDelay%

KeyMouse:
{
    GetKeyState, AState, A
    GetKeyState, SState, S
    GetKeyState, DState, D
    GetKeyState, WState, W

    if (AState = "U") && (SState = "U") && (DState = "U") && (WState = "U")
    {
    XSensitivity := 0 ; Скорость передвижения мыши по горизонтали.
    YSensitivity := 0 ; Скорость передвижения мыши по вертикали.
    }
    
    if DState = D ; Если нажать кнопку
    {
    XSensitivity += %XAcceleration%
    }

    if SState = D ;  Если нажать кнопку
    {
    YSensitivity += %XAcceleration%
    }

    if AState = D ;  Если нажать кнопку
    {
    XSensitivity += -%XAcceleration%
    }

    if WState = D ;  Если нажать кнопку
    {
    YSensitivity += -%XAcceleration%
    }

    

    if (AState = "D" || SState = "D" || DState = "D" || WState = "D") ; Проверка состояния клавиш
    {
    DllCall("mouse_event", UInt, 0x1
                              , Int, XSensitivity
                              , Int, YSensitivity
                              , UInt, 0
                              , Int, 0)
    
    }

}
Return

Joy25::
{
}
Return

И будет работать именно из-за:

Joy25::
{
}
Return

Как решить такую проблему?

4 (изменено: creature.ws, 2012-06-30 20:58:28)

Re: AHK: Эмуляция мыши при помощи клавиатуры

#Persistent
Не нужно использовать GetKeyState в цикле для определения нажата ли клавиша. Противоестественно это для autohotkey, горячие клавиши ведь существуют.

5

Re: AHK: Эмуляция мыши при помощи клавиатуры

creature.ws пишет:

#Persistent
Не нужно использовать GetKeyState в цикле для определения нажата ли клавиша. Противоестественно это для autohotkey, горячие клавиши ведь существуют.

#Persistent работает
Да, горячие клавиши существуют. Но когда есть несколько связанных хоткеев и их нужно заставить правильно работать, по-моему, лучше это делать через таймер, getkeystate, loop и if...

6

Re: AHK: Эмуляция мыши при помощи клавиатуры

Загляните в Коллекцию.

7

Re: AHK: Эмуляция мыши при помощи клавиатуры

«Делать через таймер» — равносильно созданию своей собственной замечательной конструкции одноколёсного велосипеда.
Не вижу смысла в отказе от встроенной возможности реагировать на события нажатия клавиш.

8

Re: AHK: Эмуляция мыши при помощи клавиатуры

sergeant.coolagin могу дать очень похожий пример - эмуляция джойстика, т.е. используется джойстик, а его оси 1-я эмулирует мышку, 2-я эмулирует стрелки (с ускорением через шифт) и эмуляция всех кнопок.

Я не стал приводить тут весь скрипт т.к. он весьма большой - нужно размещу, он отлажен и работоспособен на 95% (5% это недоделка ускорителя мышки, просто забыл про него, отвлёкся на другое)

"На каждое действие есть равная ему противодействующая критика." Постулат Харриссона
Для NotePad++(подсветка синтаксиса, автозавершение и плагины(AutoSave и RunMe).
OS Windows 10 x64 Pro

9 (изменено: alexii, 2012-07-06 05:18:07)

Re: AHK: Эмуляция мыши при помощи клавиатуры

Здравствуйте, подскажите как лкм повесить на кнопку 3 ? Ну то есть чтобы левый клик мыши нажимался не мышкой, а кнопкой клавиатуры. А соответственно кнопка 3 нажималась по левому клику.

Попытался вот так сделать :

3::Send, Lbutton
Lbutton:Send, 3

Но скрипт вообще не запускается.

10

Re: AHK: Эмуляция мыши при помощи клавиатуры

; стандартное действие ЛКМ при нажатом Ctrl
#If !GetKeyState("Ctrl", "P")

LButton::3
3::LButton