Using pyHook to get mouse coordinates to play back later - python

I am writing a chunk of code to get gather mouse click information using pyHook and then the win32api to get access to a click function. Essentially I am trying to use the mouse to record a pattern of clicks to be recorded and played back later.
Here is my present code:
import win32api, win32con, time, win32ui, pyHook, pythoncom
#Define the clicks in the win32api
def click(x,y):
win32api.SetCursorPos((x,y))
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,x,y,0,0)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,x,y,0,0)
def onclick(event):
click()
print event.Position
return True
hm = pyHook.HookManager()
hm.SubscribeMouseAllButtonsDown(click)
hm.HookMouse()
pythoncom.PumpMessages()
hm.UnhookMouse()
I am sure there is something stupidly simple.
Also here is the debug I got from running this:
Traceback (most recent call last):
File "C:\Python27\lib\site-packages\pyHook\HookManager.py", line 325, in MouseSwitch
return func(event)
TypeError: click() takes exactly 2 arguments (1 given)

hm.SubscribeMouseAllButtonsDown(click) -> hm.SubscribeMouseAllButtonsDown(onclick)
Removed click() call in onclick.
import win32api, win32con, time, win32ui, pyHook, pythoncom
def click(x,y):
win32api.SetCursorPos((x,y))
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,x,y,0,0)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,x,y,0,0)
def onclick(event):
print event.Position
return True
hm = pyHook.HookManager()
hm.SubscribeMouseAllButtonsDown(onclick)
hm.HookMouse()
pythoncom.PumpMessages()
hm.UnhookMouse()

I can't install pyhook, so this is a stab in the dark. I've assumed (event_x, event_y) = event.Position.
import win32api, win32con, time, win32ui, pyHook, pythoncom
#Define the clicks in the win32api
def click(x,y):
win32api.SetCursorPos((x,y))
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,x,y,0,0)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,x,y,0,0)
def onclick(event):
print event.Position
(event_x, event_y) = event.Position
click(event_x, event_y)
return True
hm = pyHook.HookManager()
hm.SubscribeMouseAllButtonsDown(onclick)
hm.HookMouse()
pythoncom.PumpMessages()
hm.UnhookMouse()

click() gets 2 parameters and you are passing a tuple (event.position is a tuple). Do instead:
def click((x,y)):

Related

How to stop a function in python?

I want to stop the function so I can run a different one, this is my code:
from pynput import keyboard
import os, sys
import pygame
import time
from pygame import mixer
from pynput import mouse
from pygame import mixer
pygame.mixer.init(buffer=10)
from pynput.keyboard import Key, Listener
def click0():
def on_press(key):
print("HARD CLICK")
def click1():
def on_press(key):
print("MEM CLICK")
def click2():
def on_press(key):
print("SOFT CLICK")
# Collect events until released
with Listener(
on_press=on_press,
on_release=on_release) as listener:
listener.join()
while True:
click0()
time.sleep(1) #sleep for 1 second
click1()
time.sleep(2) #sleep for 1 second
click2()
I want it to be like this:
from pynput import keyboard
import os, sys
import pygame
import time
from pygame import mixer
from pynput import mouse
from pygame import mixer
pygame.mixer.init(buffer=10)
from pynput.keyboard import Key, Listener
def click0():
def on_press(key):
print("HARD CLICK")
def click1():
def on_press(key):
print("MEM CLICK")
def click2():
def on_press(key):
print("SOFT CLICK")
# Collect events until released
with Listener(
on_press=on_press,
on_release=on_release) as listener:
listener.join()
while True:
click0()
time.sleep(1) #sleep for 1 second
click0(quit)
click1()
time.sleep(2) #sleep for 1 second
click1(quit)
click2()
So I want to code the have 3 funcstions and it loops taking turns like: click1 (IS LOOPING), click2 (IS LOOPING), click3 (IS LOOPING), click1 (IS LOOPING), click..
But I want to stop the funcstion before running a diffent one like: click1 (IS LOOPING), click1 (STOPPED) click2 (IS LOOPING), click2 (STOPPED) click3 (IS LOOPING), click3 (STOPPED) click..
Any help please?
Consider using the async & return operators:
async def click0():
#.. do things
return
async def click1():
#.. do things again
return
async def main():
while True:
await click0()
await click1()
This await method essentially waits till a function is finish before moving onto the next line, so here the click0 function will need to complete before click1() executes,
alternatively, you can call click1 from click0, and click2 from click1 and so on...

How do I get my code to loop until I press a button (Lego EV3)

The question pure and simple. I've tried using while loops, rearranging code, but all that happens is that the program starts when i press the button or does absolutely nothing at all. Can anyone see what I am doing wrong?
#!/usr/bin/env python3
from ev3dev2.motor import MoveTank, OUTPUT_B, OUTPUT_C
from ev3dev2.button import Button
from ev3dev2.sound import Sound
from time import sleep
import time
sound = Sound()
btn = Button()
tank_pair = MoveTank(OUTPUT_B, OUTPUT_C)
def movement(left_speed, right_speed, rotations):
tank_pair.on_for_rotations(left_speed, right_speed, rotations, brake=True, block=True)
while not btn.any():
movement(20,20,10)
movement(-100,0,1.5)
movement(20,20,10)
sleep(0.01)
while btn.any():
sleep(0.01)
tank_pair.off()
sound.beep()
exit()
you can break your main loop using this
pip install keyboard
then
import keyboard
while True:
# do something
if keyboard.is_pressed("q"):
print("q pressed, ending loop")
break
Your indentation is incorrect.
from ev3dev2.motor import MoveTank, OUTPUT_B, OUTPUT_C
from ev3dev2.button import Button
from ev3dev2.sound import Sound
from time import sleep
import time
sound = Sound()
btn = Button()
tank_pair = MoveTank(OUTPUT_B, OUTPUT_C)
def movement(left_speed, right_speed, rotations):
tank_pair.on_for_rotations(left_speed, right_speed, rotations, brake=True, block=True)
while not btn.any():
movement(20,20,10)
movement(-100,0,1.5)
movement(20,20,10)
sleep(0.01)
while btn.any():
sleep(0.01)
tank_pair.off()
sound.beep()
exit()

How can pythoncom.PumpMessages() restart after PostQuitMessage?

I use a hook to check for Mouse Event and Keyboard Event, and I create a new thread for the hook because I have some other work to do.
The hook thread consumes CPU all the time, so I want to pause it occasionally (for efficiency). I tried using PostQuitMessage() to stop it and then wait to restart the thread and PumpMessages() at the right time. but it doesn't work.
I am looking forward to receiving your answers!
The following is the main part of the code,you can run it then will get the problem.
ps. Excuse my broken English~_~
# -*- coding: utf-8 -*- #
#Python version:3.5.4
from win32 import win32process
import time
import threading
#import win32
import psutil
import PyHook3 as pyHook
import pythoncom
import win32gui, win32ui, win32con, win32api
def OnMouseEvent(event):
print('-----Mouse-----', event)
return True
def OnKeyboardEvent(event):
print('-----key-----', event)
if str(event.Key)=='F12':
win32api.PostQuitMessage()
return True
def InputScan():
print('-----InputScan-----')
hm.MouseLeftDown = OnMouseEvent
hm.HookMouse()
hm.KeyDown = OnKeyboardEvent
hm.HookKeyboard()
#first time is worked normally,but re-execution not working
pythoncom.PumpMessages()
return True
print('start program...')
threads = []
nowThreadsName=[]
hm = pyHook.HookManager()
try:
ThreadIS = threading.Thread(target=InputScan, name='ThreadIS', args=())
ThreadIS.setDaemon(True)
threads.append(ThreadIS)
ThreadIS.start()
except:
print("Error:--")
while 1:
#some other works
time.sleep(5)
open_str = input("whether restart(anykey): \n")
nowthread = threading.enumerate()
nowThreadsName.clear()
print("nowThreadsNameclear=",nowThreadsName)
for i in nowthread:
nowThreadsName.append(i.getName())
print("nowThreadsName=",nowThreadsName)
if 'ThreadIS' in nowThreadsName:
pass
else:
t = threading.Thread(target=InputScan, name='ThreadIS', args=())
t.setDaemon(True)
t.start() #why it dosen't work??
pass
pass

I want to stop pythoncom working

I was writing a code about keylogging by pyHook. The following codes are example:
import pythoncom as pc, pyHook as ph
def KeyboardHook(event):
print chr(event.Ascii)
return True
hm = ph.HookManager()
hm.KeyDown = KeyboardHook
hm.HookKeyboard()
pc.PumpMessages()
I want to stop pythoncom's PumpMessages method for a while later (for example five seconds). But I couldn't find any answer to it.
I use: Windows 7, Python2.7
Thanks for answer.
You will have to use pythoncom.PumpWaitingMessages which is not blocking.
import pythoncom as pc, pyHook as ph
import time
def KeyboardHook(event):
print chr(event.Ascii)
return True
hm = ph.HookManager()
hm.KeyDown = KeyboardHook
hm.HookKeyboard()
while time.clock() < 5:
pc.PumpWaitingMessages()

disable or lock mouse and keyboard in Python?

Is there a way of disabling or locking mouse and keyboard using python? I want to freeze the mouse and disable the keyboard.
I haven't tested (actually I've tested the mouse part, and it annoyingly works) but something like this using pyhook would do what you want:
import pythoncom, pyHook
def uMad(event):
return False
hm = pyHook.HookManager()
hm.MouseAll = uMad
hm.KeyAll = uMad
hm.HookMouse()
hm.HookKeyboard()
pythoncom.PumpMessages()
I have extended Fábio Diniz's answer to a class which provides both a block() and an unblock() function which block (selectively) mouse/keyboard inputs. I also added a timeout functionality which (hopefully) addresses the annoyance of locking oneself out.
import pyHook
from threading import Timer
import win32gui
import logging
class blockInput():
def OnKeyboardEvent(self,event):
return False
def OnMouseEvent(self,event):
return False
def unblock(self):
logging.info(" -- Unblock!")
if self.t.is_alive():
self.t.cancel()
try: self.hm.UnhookKeyboard()
except: pass
try: self.hm.UnhookMouse()
except: pass
def block(self, timeout = 10, keyboard = True, mouse = True):
self.t = Timer(timeout, self.unblock)
self.t.start()
logging.info(" -- Block!")
if mouse:
self.hm.MouseAll = self.OnMouseEvent
self.hm.HookMouse()
if keyboard:
self.hm.KeyAll = self.OnKeyboardEvent
self.hm.HookKeyboard()
win32gui.PumpWaitingMessages()
def __init__(self):
self.hm = pyHook.HookManager()
if __name__ == '__main__':
logging.basicConfig(level=logging.INFO)
block = blockInput()
block.block()
import time
t0 = time.time()
while time.time() - t0 < 10:
time.sleep(1)
print(time.time() - t0)
block.unblock()
logging.info("Done.")
You can have a look at the main routine for example usage.
For me, just two lines of programming solved the problem:
from ctypes import *
ok = windll.user32.BlockInput(True) #enable block
#or
ok = windll.user32.BlockInput(False) #disable block
Totally different take since all the solutions mentioned above use a quiet outdated library(pyhook) and this pyhook method personally didnt work for me.
import keyboard
from pynput.mouse import Controller
from time import sleep
def blockinput():
global block_input_flag
block_input_flag = 1
t1 = threading.Thread(target=blockinput_start)
t1.start()
print("[SUCCESS] Input blocked!")
def unblockinput():
blockinput_stop()
print("[SUCCESS] Input unblocked!")
def blockinput_start():
mouse = Controller()
global block_input_flag
for i in range(150):
keyboard.block_key(i)
while block_input_flag == 1:
mouse.position = (0, 0)
def blockinput_stop():
global block_input_flag
for i in range(150):
keyboard.unblock_key(i)
block_input_flag = 0
blockinput()
print("now blocking")
sleep(5)
print("now unblocking")
I just slightly modified the #Robert code and instead of the time I used external interrupt to close the program i.e. if you connect any external drive then the program gets close and your mouse and keyboard will be working perfectly.
import pyHook
from threading import Timer
import win32gui
import logging
import win32file
def locate_usb():#this will check any external Drives
drive_list = []
drivebits = win32file.GetLogicalDrives()
# print(drivebits)
for d in range(1, 26):
mask = 1 << d
if drivebits & mask:
# here if the drive is at least there
drname = '%c:\\' % chr(ord('A') + d)
t = win32file.GetDriveType(drname)
if t == win32file.DRIVE_REMOVABLE:
drive_list.append(drname)
return drive_list
class blockInput():
def OnKeyboardEvent(self,event):
return False
def OnMouseEvent(self,event):
return False
def unblock(self):
try: self.hm.UnhookKeyboard()
except: pass
try: self.hm.UnhookMouse()
except: pass
def block(self ,keyboard = True, mouse = True):
while(1):
if mouse:
self.hm.MouseAll = self.OnMouseEvent
self.hm.HookMouse()
if keyboard:
self.hm.KeyAll = self.OnKeyboardEvent
self.hm.HookKeyboard()
win32gui.PumpWaitingMessages()
cg= locate_usb()
if cg:
break
def __init__(self):
self.hm = pyHook.HookManager()
if __name__ == '__main__':
block = blockInput()
block.block()
block.unblock()
I hope this code will help you
Since 2018, you can now use pynput (v1.4+) to suppress keyboard and mouse events on Windows, Mac, and Linux.
import pynput
# Disable mouse and keyboard events
mouse_listener = pynput.mouse.Listener(suppress=True)
mouse_listener.start()
keyboard_listener = pynput.keyboard.Listener(suppress=True)
keyboard_listener.start()
# Enable mouse and keyboard events
mouse_listener.stop()
keyboard_listener.stop()
This also disables mouse scrolling and clicking.
However, this does not stop users from pressing Ctrl+Alt+Del on Windows. But you can run the script in an elevated command prompt, and the mouse and keyboard will still be disabled, even if they opened Task Manager using Ctrl+Alt+Delete, so there is no harm done (apparently there are way to actually prevent Ctrl+Alt+Delete, but do your own research for that)
You can use pyautogui to do this. Though I recommend adding keyboard for making a stopping key. First, you want to install pyautogui and keyboard.
Please note: this only disables the mouse not the keyboard, that is a very bad idea.
pip install pyautogui
pip install keyboard
Ok, with that sorted, we have to actually make the disabler.
import pyautogui
import keyboard
stopKey = "s" #The stopKey is the button to press to stop. you can also do a shortcut like ctrl+s
maxX, maxY = pyautogui.size() #get max size of screen
While True:
if keyboard.is_pressed(stopKey):
break
else:
pyautogui.moveTo(maxX/2, maxY/2) #move the mouse to the center of the screen
Ok, but there is 2 ways to get out of this. pressing S, and also quickly moving the mouse to one of the corners of the screen (that is a pyautogui failsafe, but we can disable that). If you want to disable the failsafe, add this after the imports:
pyautogui.FAILSAFE = False
Please note that disabling the failsafe is NOT recommended!
Ok, so now the only way to exit is the S key. If you want to stop this somewhere else in your program, do this:
pyautogui.press(stopKey)
Ok, so its not perfect, but it will stop you from doing basically anything with your mouse.

Categories

Resources