Что нового

[Мышь, клавиатура] Определение активности Mouse Wheel

Dimmak

Знающий
Сообщения
185
Репутация
9
Как в библиотеке isPressed.
Код:
DllCall($dll_user32, "short", "GetAsyncKeyState", "int", '0x' & '$клавиша')

(клавиша не блокируется а просто определяется нажата ли она).
Нужно то же самое для Mouse Wheel и самым простым( быстродействие ) способом.

Не советуйте мне библиотеки( к примеру isPressedEx & MouseOnEvent ).
Просто напишите, пожалуйста, пару строчек кода для определения активности события Mouse Wheel( прокрутка колесика мышки вверх, к примеру ).
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,670
Репутация
2,473
Re: [Мышь, клавиатура] Определение активности Mouse Wheel без низкоуровневой блокировки

Dimmak [?]
Просто напишите, пожалуйста, пару строчек кода для определения активности события Mouse Wheel
С чего такая уверенность что это можно написать в пару строк?
 
Автор
Dimmak

Dimmak

Знающий
Сообщения
185
Репутация
9
Re: [Мышь, клавиатура] Определение активности Mouse Wheel без низкоуровневой блокировки

С чего такая уверенность что это можно написать в пару строк?
Ответ ясен. От моей некомпетентности.
Пытался разобраться с библиотекой MouseOnEvent - там низкоуровневый хук на игнорирование, а он мне не нужен. Там я и запутался...
Creator, подскажи пожалуйста!
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,670
Репутация
2,473
Re: [Мышь, клавиатура] Определение активности Mouse Wheel без низкоуровневой блокировки

Dimmak [?]
Пытался разобраться с библиотекой MouseOnEvent - там низкоуровневый хук на игнорирование, а он мне не нужен.
К чему эти сложности, нужен хук или не нужен, для использования библиотеки не нужно об этом думать:

Код:
#include "MouseOnEvent.au3"

HotKeySet("{ESC}", "_Quit")

_MouseSetOnEvent($MOUSE_WHEELDOWN_EVENT, "_MouseWheel_Events")
_MouseSetOnEvent($MOUSE_WHEELUP_EVENT, "_MouseWheel_Events")

Sleep(10000)

Func _MouseWheel_Events($iEvent)
	Switch $iEvent
		Case $MOUSE_WHEELDOWN_EVENT
			ToolTip("Wheel mouse button Pressed down")
		Case $MOUSE_WHEELUP_EVENT
			ToolTip("Wheel mouse button released")
	EndSwitch
	
	Return 0 ;1 to Block the event
EndFunc

Func _Quit()
	Exit
EndFunc
 

AZJIO

Меценат
Меценат
Сообщения
2,805
Репутация
1,168
Re: [Мышь, клавиатура] Определение активности Mouse Wheel без низкоуровневой блокировки

Dimmak
Может это чем-то поможет
 
Автор
Dimmak

Dimmak

Знающий
Сообщения
185
Репутация
9
Re: [Мышь, клавиатура] Определение активности Mouse Wheel без низкоуровневой блокировки

CreatoR, AZJIO Спасибо! :smile:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,722
Re: [Мышь, клавиатура] Определение активности Mouse Wheel без низкоуровневой блокировки

Есть всего два варианта для глобального отслеживания прокрутки колеса мыши - Hook и Raw Input (предпочтительнее). Первое вам дал AZJIO, второе можете посмотреть в примере к функции _WinAPI_RegisterRawInputDevices() из WinAPIEx UDF. И оба способа далеко не в две строчки.
 
Автор
Dimmak

Dimmak

Знающий
Сообщения
185
Репутация
9
Re: [Мышь, клавиатура] Определение активности Mouse Wheel без низкоуровневой блокировки

Спасибо Yashied.
Заодно обновил WinAPIEx. Хороший пример с _WinAPI_RegisterRawInputDevices() с мышкой. :ok:
Как осуществить тоже самое, но только без GUI? :scratch:

С помощью функции _WinAPI_EnumRawInputDevices() получаю хэндл устройства,
но насколько я понял, функция _WinAPI_GetRawInputData() не работает напрямую с input device handle. :-\
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,670
Репутация
2,473
Yashied [?]
Есть всего два варианта для глобального отслеживания прокрутки колеса мыши - Hook и Raw Input (предпочтительнее)
Чем предпочтительнее?

второе можете посмотреть в примере к функции _WinAPI_RegisterRawInputDevices() из WinAPIEx UDF
Действительно отличный пример. Можно ли это использовать для отлова ввода боковых кнопок мышки (XButton)?
 
Автор
Dimmak

Dimmak

Знающий
Сообщения
185
Репутация
9
Можно ли это использовать для отлова ввода боковых кнопок мышки (XButton)?
Да, можно.
Я пробовал
Код:
$RI_MOUSE_BUTTON_4_DOWN, $RI_MOUSE_BUTTON_4_UP
и $RI_MOUSE_BUTTON_5_UP, $RI_MOUSE_BUTTON_5_DOWN
вместо средней кнопки - обе кнопки отлавливаюся. :ok:
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,722
CreatoR сказал(а):
Чем предпочтительнее?

Во-первых, ты не вмешиваешься в систему, т.е. не тормозишь ничего своим хуком. Во-вторых, если выполнение хука превысит определенное время, то его банально выкинет. В-третьих, MSDN так советует.

Вообще, если взять какую-нибудь программу на AutoIt, которая использует хук клавиатуры или мыши, и запустить ее несколько раз, то задержка будет уже ощутима. Поэтому лучше оформлять процедуру хука в виде DLL на каком-нибудь компилируемом ЯП.
 
Автор
Dimmak

Dimmak

Знающий
Сообщения
185
Репутация
9
Yashied
Может ли функция
Код:
_WinAPI_GetRawInputData()

работать без GUI?
Если да, то откуда брать $lParam?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,722
Dimmak сказал(а):
Может ли функция _WinAPI_GetRawInputData() работать без GUI?

Нет не может. Любая программа для Windows имеет хотя-бы одно GUI. AutoIt, например, всегда имеет скрытое окно, но работать с ним вы не можете. Просто создайте свое скрытое окно, которое будет получать сообщения.
 
Автор
Dimmak

Dimmak

Знающий
Сообщения
185
Репутация
9
Прошу помощи в оптимизации быстродействия кода ( Mouse Wheel Raw Input ) ;)
Код:
#Include <APIConstants.au3>
#Include <GUIConstantsEx.au3>
#Include <WinAPIEx.au3>
     	       ProcessSetPriority( @AutoItPID, 4 ) ; HighPriority
	Global $dll_user32 = DllOpen('user32.dll')
	Global $dll_kernel32 = DllOpen('kernel32.dll')

Global $hForm, $tRID, $pRID
Global $Data, $Flags

; Create GUI
$hForm = GUICreate('MyGUI', 160, 212, @DesktopWidth - 179, @DesktopHeight - 283, _
BitOR($WS_CAPTION, $WS_POPUP, $WS_SYSMENU), $WS_EX_TOPMOST)

$tRID = DllStructCreate($tagRAWINPUTDEVICE)
DllStructSetData($tRID, 'UsagePage', 0x01) ; Generic Desktop Controls
DllStructSetData($tRID, 'Usage', 0x02) ; Mouse
DllStructSetData($tRID, 'Flags', $RIDEV_INPUTSINK)
DllStructSetData($tRID, 'hTarget', $hForm)
$pRID = DllStructGetPtr($tRID)

; Register HID input to obtain row input from mice
_WinAPI_RegisterRawInputDevices($pRID)

; Register WM_INPUT message
GUIRegisterMsg($WM_INPUT, 'WM_INPUT')

;GUISetState()

While 1
;~ 	If GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop
    DllCall($dll_kernel32, 'DWORD', 'Sleep', 'int', 1) ; Sleep 1ms
WEnd


Func WM_INPUT($hWnd, $iMsg, $wParam, $lParam)

	Local $tRIM = DllStructCreate($tagRAWINPUTMOUSE)

; _WinAPI_GetRawInputData()
DllCall($dll_user32, 'uint', 'GetRawInputData', 'ptr', $lParam, 'uint', $RID_INPUT, 'ptr', _
DllStructGetPtr($tRIM), 'uint*', DllStructGetSize($tRIM), 'uint', 16)

	$Flags = DllStructGetData($tRIM, 'ButtonFlags')

				If BitAND($Flags, $RI_MOUSE_WHEEL) Then
					$Data = _WinAPI_WordToShort(DllStructGetData($tRIM, 'ButtonData'))
					If $Data > 0 Then
ConsoleWrite( 'Up' )
					Else
ConsoleWrite( 'Down' )
					EndIf
				EndIf

	Return ;$GUI_RUNDEFMSG
EndFunc   ;==>WM_INPUT


	DllClose( $dll_user32 )
	DllClose( $dll_kernel32 )
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,722
И что тут оптимизировать?
 

Dm666

Осваивающий
Сообщения
221
Репутация
48
Код очень подошел мне для использования... Как раз искал что-то подобное. Только хочется еще отслеживать нажатие на колесо мыши. Как этого добиться?
В Dll* командах не понимаю вообще ничего (и научить некому), поэтому пробовал по аналогии, добавил
Код:
If BitAND($Flags, $RI_MOUSE_MIDDLE_BUTTON_DOWN) Then
		$Data = _WinAPI_WordToShort(DllStructGetData($tRIM, 'ButtonData'))
		ConsoleWrite( 'WheelDown' )
	EndIf

Зачем-то срабатывает дуплетом, 2 раза за каждое нажатие. Как победить?
 

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,722
Dm666 сказал(а):
Зачем-то срабатывает дуплетом, 2 раза за каждое нажатие. Как победить?

Что значит дуплетом? В примере из WinAPIEx UDF фиксируется нажатие на среднюю кнопку (колесо).
 

Dm666

Осваивающий
Сообщения
221
Репутация
48
Yashied [?]
Что значит дуплетом?
Я имел ввиду что при выполнении вышеприведенного кода при каждом щелчке колесом в консоль пишется WheelDownWheelDown. Первый WheelDown пишется при нажатии на колесо, второй при его отпускании. Как бы отделить только нажатие?

В примере из WinAPIEx UDF фиксируется нажатие на среднюю кнопку (колесо).
В примере тоже срабатывает дважды. Если вствить, допустим,Beep:

Код:
Case BitAND($Flags, $RI_MOUSE_MIDDLE_BUTTON_DOWN)
		Beep (1000,100)

то слышно что пищит дважды, хотя по логике должно бы только раз..
 
Автор
Dimmak

Dimmak

Знающий
Сообщения
185
Репутация
9
Код:
#Include <APIConstants.au3>
#Include <GUIConstantsEx.au3>
#Include <WinAPIEx.au3>

	Global $dll_user32 = DllOpen('user32.dll')
	Global $dll_kernel32 = DllOpen('kernel32.dll')

Global $hForm, $tRID, $pRID
Global $Data, $Flags

Global Const $mb_1d = 0x0001 ; d - нажтие, u - отпускание
Global Const $mb_1u = 0x0002
Global Const $mb_2d = 0x0004
Global Const $mb_2u = 0x0008
Global Const $mb_3d = 0x0010
Global Const $mb_3u = 0x0020
Global Const $mb_4d = 0x0040
Global Const $mb_4u = 0x0080
Global Const $mb_5d = 0x0100
Global Const $mb_5u = 0x0200
Global Const $wh = 0x0400

Global $aMouse[6]      = [ 6,       $mb_1d, $mb_2d, $mb_3d, $mb_4d, $mb_5d ] ; Только нажатие

; Global $Funcs[5] = [ 5,      'Func1', 'Func2']

; Create GUI
$hForm = GUICreate('MyGUI', 160, 212, @DesktopWidth - 179, @DesktopHeight - 283, _
BitOR($WS_CAPTION, $WS_POPUP, $WS_SYSMENU), $WS_EX_TOPMOST)

$tRID = DllStructCreate($tagRAWINPUTDEVICE)
DllStructSetData($tRID, 'UsagePage', 0x01) ; Generic Desktop Controls
DllStructSetData($tRID, 'Usage', 0x02) ; Mouse
DllStructSetData($tRID, 'Flags', $RIDEV_INPUTSINK)
DllStructSetData($tRID, 'hTarget', $hForm)
$pRID = DllStructGetPtr($tRID)

; Register HID input to obtain row input from mice
_WinAPI_RegisterRawInputDevices($pRID)

; Register WM_INPUT message
GUIRegisterMsg($WM_INPUT, 'WM_INPUT')

;GUISetState()

While 1
;~ 	If GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop
    DllCall($dll_kernel32, 'DWORD', 'Sleep', 'int', 1) ; Sleep 1ms
WEnd


Func WM_INPUT($hWnd, $iMsg, $wParam, $lParam)

	Local $tRIM = DllStructCreate($tagRAWINPUTMOUSE)

; _WinAPI_GetRawInputData()
DllCall($dll_user32, 'uint', 'GetRawInputData', 'ptr', $lParam, 'uint', $RID_INPUT, 'ptr', _
DllStructGetPtr($tRIM), 'uint*', DllStructGetSize($tRIM), 'uint', 16)

	$Flags = DllStructGetData($tRIM, 'ButtonFlags')

	For $i = 1 to 5 ; 5 кнопок нажатие только
		If BitAND($Flags, $aMouse[$i]) Then
			; Call( $Funcs[$i] )
		EndIf
	Next

				If BitAND($Flags, $RI_MOUSE_WHEEL) Then
					$Data = _WinAPI_WordToShort(DllStructGetData($tRIM, 'ButtonData'))
					If $Data > 0 Then
ConsoleWrite( 'Up' )
					Else
ConsoleWrite( 'Down' )
					EndIf
				EndIf

	Return ;$GUI_RUNDEFMSG
EndFunc   ;==>WM_INPUT


	DllClose( $dll_user32 )
	DllClose( $dll_kernel32 )
 

Dm666

Осваивающий
Сообщения
221
Репутация
48
Спасибо за участие. Почти то. Вот такой вариант, так будет понятнее
Код:
#include <APIConstants.au3>
#include <GUIConstantsEx.au3>
#include <WinAPIEx.au3>
HotKeySet("{Esc}", "_Exit")

Global $dll_user32 = DllOpen('user32.dll')
Global $dll_kernel32 = DllOpen('kernel32.dll')

Global $hForm, $tRID, $pRID
Global $Data, $Flags

Global Const $mb_1d = 0x0001 ; d - нажтие, u - отпускание
Global Const $mb_1u = 0x0002
Global Const $mb_2d = 0x0004
Global Const $mb_2u = 0x0008
Global Const $mb_3d = 0x0010
Global Const $mb_3u = 0x0020
Global Const $mb_4d = 0x0040
Global Const $mb_4u = 0x0080
Global Const $mb_5d = 0x0100
Global Const $mb_5u = 0x0200
Global Const $wh = 0x0400

Global $aMouse[6] = [6, $mb_1d, $mb_2d, $mb_3d, $mb_4d, $mb_5d] ; Только нажатие

; Global $Funcs[5] = [ 5,      'Func1', 'Func2']

; Create GUI
$hForm = GUICreate('MyGUI', 160, 212, @DesktopWidth -179, @DesktopHeight -283, _
		BitOR($WS_CAPTION, $WS_POPUP, $WS_SYSMENU), $WS_EX_TOPMOST)

$tRID = DllStructCreate($tagRAWINPUTDEVICE)
DllStructSetData($tRID, 'UsagePage', 0x01) ; Generic Desktop Controls
DllStructSetData($tRID, 'Usage', 0x02) ; Mouse
DllStructSetData($tRID, 'Flags', $RIDEV_INPUTSINK)
DllStructSetData($tRID, 'hTarget', $hForm)
$pRID = DllStructGetPtr($tRID)

; Register HID input to obtain row input from mice
_WinAPI_RegisterRawInputDevices($pRID)

; Register WM_INPUT message
GUIRegisterMsg($WM_INPUT, 'WM_INPUT')

;GUISetState()

While 1
;~  If GUIGetMsg() = $GUI_EVENT_CLOSE Then ExitLoop
	DllCall($dll_kernel32, 'DWORD', 'Sleep', 'int', 1) ; Sleep 1ms
WEnd

Func WM_INPUT($hWnd, $iMsg, $wParam, $lParam)
	
	Local $tRIM = DllStructCreate($tagRAWINPUTMOUSE)
	
	; _WinAPI_GetRawInputData()
	DllCall($dll_user32, 'uint', 'GetRawInputData', 'ptr', $lParam, 'uint', $RID_INPUT, 'ptr', _
			DllStructGetPtr($tRIM), 'uint*', DllStructGetSize($tRIM), 'uint', 16)
	
	$Flags = DllStructGetData($tRIM, 'ButtonFlags')
	
	For $i = 1 To 5 ; 5 кнопок нажатие только
		If BitAND($Flags, $aMouse[$i]) Then
			_ButtonDown($i)
		EndIf
	Next
	
	If BitAND($Flags, $RI_MOUSE_WHEEL) Then
		$Data = _WinAPI_WordToShort(DllStructGetData($tRIM, 'ButtonData'))
		If $Data > 0 Then
			ConsoleWrite('Up')
		Else
			ConsoleWrite('Down')
		EndIf
	EndIf
	
;~     Return ;$GUI_RUNDEFMSG
EndFunc ;==>WM_INPUT

Func _ButtonDown($i)
	ConsoleWrite('-> Button' & $i & @CRLF)
	Beep(1000, 100)
EndFunc

Func _Exit()
	Exit
EndFunc

DllClose($dll_user32)
DllClose($dll_kernel32)

Почему при щелчке колесом _ButtonDown() вызывается дважды? Все остальные кнопки отрабатывают нормально, по одному разу. Как избежать двойного срабатывания?
Может я странного хочу?
 
Верх