I wanted to write a program in Python for Windows that would act as a clicker, in which according to a key the user presses a click is made at a known location on the screen. This is used for an automated option selection from a list in a webpage. I have the clicking part working, but I wanted to be able to make several clicks during execution, as if there is a quiz with multiple lists one after another.
One option is to make a while loop with getch() from msvcrt. The thing is after a click outside the cmd its window is no longer selected, but rather the window where the destination point is located. Therefore, the script stops being active and the user cannot choose another location. A workaround is to click the cmd window to return the focus to it and be able to do any more clicks. To solve this, it would be necessary to create a service or, according to #Sanju, a thread.
The other option is to use a keylogger such as PyHook, which seems like the way to go. However, the problem is that the window where I want to use it in, a webpage in flash or another animations engine, causes an error that some users have found using this keylogger for example in Skype and is being described here. In my case, it also happens with this webpage and either when the click is made on the window itself or when the key is pressed with the window selected.
My base code is presented below, where click(...) would normally contain the coordinates as argument but they are being omitted for simplicity. In this case, 0 ends the program and there are three options being chosen with the numbers 1-3.
import msvcrt, win32api, win32con
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)
key=0
while key!=b'0':
key=msvcrt.getch()
if key==b'1':
click(...)
elif key==b'2':
click(...)
elif key==b'3':
click(...)
The attempts below try to implement #Sanju's suggestion, first with the whole while inside the thread and then with the queue, both not working as expected...
import threading, msvcrt, win32api, win32con
def MyThread():
key=0
while key!=b'0':
key=msvcrt.getch()
if key==b'1':
...
def click(x,y):
...
threading.Thread(target=MyThread,args=[]).start()
.
import queue, threading, msvcrt, win32api, win32con
def MyThread(key):
while key.get()!=b'0':
key.put(msvcrt.getch())
if key.get()==b'1':
...
def click(x,y):
...
key=queue.Queue()
key.put(0)
threading.Thread(target=MyThread,args=[key]).start()
The other attempt uses PyHook, but it's still facing the aforementioned issue.
import pyHook, pythoncom, win32api, win32con
def OnKeyboardEvent(event):
if event.Key=='Numpad1':
...
def click(x,y):
...
hm=pyHook.HookManager()
hm.KeyDown=OnKeyboardEvent
hm.HookKeyboard()
pythoncom.PumpMessages()
All you need here is move your click part to a thread and share the user input using a shareble object such as queue. It sounds like a overkill , but that's the way to keep your tasks in background.
And BTW, you have many GUI application frameworks available in Python like tkinter ,wxpython which can ease your objective.
Related
I want to change the active window to a particular one using python. Here is a working example:
import pygetwindow as gw
win = gw.getWindowsWithTitle('editor')[0]
win.activate()
What I'd like to do however, is triggering the switch of windows using a hotkey, for instance like this:
import pygetwindow as gw
import keyboard as kb
def change_window():
win = gw.getWindowsWithTitle('editor')[0]
win.activate()
kb.add_hotkey('q', change_window)
kb.wait('esc')
I would expect the above code to do exactly the same as the first one after pressing the "q" key. However, the second code produces an error message. I really can't understand how the fact that it is triggered by a hotkey could change anything. I have tried different hotkeys and inserted a few time.sleep in between to see if it has anything to do with me still having the hotkey pressed, but to no success. It even works if I just call the function directly in the source code.
I would appreciate your feedback very much. I'm using PyCharm on Windows 11.
Is there a way to disable (keyboard) input on windows with python. I would like to convert this program to exe and the
from ctypes import *
ok = windll.user32.BlockInput(True) #enable block
method is not suitable for that (as it needs admin privileges). I looked at other articles with described how using the pyHook would work. Unfortunatelly this method is a bit old and does not work for me anymore, it just makes the mouse and keyboard lag a little bit.
There is a working method by just putting keystrokes (from for example the pynput library) in a while loop, so it just spams keystrokes and the user can not overwrite this by typing lets say alt+f4. This is a very dirty way and I would like a cleaner way(this method causes the computer to lag for a minute because it cant comprehend that amount of input in such a short time)
#### Blocking Keyboard ####
import keyboard
#blocks all keys of keyboard
for i in range(150):
keyboard.block_key(i)
So I've been working on a small project which will essentially be a macros program. The idea is to use a small external numpad with custom labels to click certain areas of the screen which correspond to buttons. I've got this all working beautifully with one minor (or major?) caveat which is the fact that I cannot differentiate between keyboards. Ideally I'd like to be able to still use my main keyboard and numpad normally. My code below for a sample key:
import keyboard
import pynput
from pynput.mouse import Button, Controller
import time
mouse = Controller()
tab = (1639, 16)
def handler():
print(keyboard.KeyboardEvent.device)
prev = mouse.position
mouse.position = tab
mouse.click(Button.left, 1)
mouse.position = prev
keyboard.add_hotkey("a", handler, suppress=True)
while True:
time.sleep(0.1)
So you can see here I am using the keyboard and pynput libraries. In the docs for the keyboard library, it notes an issue where on windows specifically, keyboard.KeyboardEvent.device returns "None" always.
I looked around a bit at various solutions for using raw input, but I wasn't able to really find anything applicable to my situation, and anything that looked remotely close was admittedly beyond my skill level. Anybody have any thoughts? Thanks.
I'm trying to set up a bot that does things for me, at the moment I have to be in the same window so that it works. Is it possible to be able to change my window (e.g using google chrome) while the bot is running on that specific application?
Also if you're asking about what application its, its Runescape just an old game and I'm just using it to learn more about python.
I couldn't find any information online about any module that does this sadly.
from pynput.mouse import Button, Controller
from time import sleep
from random import randint, uniform
def move_mouse(next_pos):
sleep(uniform(0.1,0.2))
mouse.position = (randint(int(round(next_pos[0])), int(round(next_pos[2]))), randint(int(round(next_pos[1])), int(round(next_pos[3]))))
sleep(uniform(1,1.2))
mouse.click(Button.left, 1)
mouse = Controller()
print(mouse.position)
shaft = [ 1299.25, 590.48828125, 1315.6171875, 610.69921875]
box = [705.01171875, 600.671875, 957.640625, 616.37109375]
sleep(2)
while True:
move_mouse(shaft)
move_mouse(box)
sleep(71)
So far everything works perfectly I get no errors what so ever. All I need is for it to click on a specific application.
I am working on a program to make python auto click and type something in. I know this has been done before and asked before but no one has asked about recording mouse clicks to be "Played back" later on. I have the basic code set up from tutorials all over the place. I am wondering if I can get a hand with this. Here is what I have to this point:
import win32api, win32con
import time
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)
print "Clicking 300, 300"
click(300,300)
time.sleep(3)
print "Clicking 800, 800"
click(800, 800)
How do I make this so the user can input and save a pre-generated script for clicks?
Well, I don't have any experience with the Win32 API, however, it should work along those lines:
The Module you are using needs to let you define a callback method for when a click happens
You somewhere set a boolean that tells you that you are currently recorded.
Your callback method stores tuples in a list:
The tuples store the timestamp (time.time) and the coordinates.
You can even store more information, like right-click or whatever.
When you are done recording you should have every informationen necessary to start replaying :)
(You may also consider this post)
Hope it helps!