我想用Python为Windows编写一个程序,充当点击器,根据用户按下的键,在屏幕上的已知位置进行点击。这用于从网页列表中自动选择选项。我的点击部分可以正常工作,但我希望能够在执行过程中进行多次点击,就像有一个包含多个列表的测验一样。
一种选择是使用 msvcrt
中的 getch()
进行 while 循环。问题是,在 cmd 外部单击后,不再选择其窗口,而是选择目标点所在的窗口。因此,脚本停止事件,用户无法选择其他位置。解决方法是单击 cmd 窗口以将焦点返回到该窗口,并能够进行更多单击。为了解决这个问题,有必要创建一个服务,或者根据 @Sanju 的说法,创建一个线程。
另一个选择是使用键盘记录器,例如 PyHook,这似乎是可行的方法。但是,问题是我想在其中使用它的窗口(Flash 或其他动画引擎中的网页)会导致一些用户在 Skype 中使用此键盘记录器(例如在 Skype 中)时发现的错误,并且正在描述 here 。就我而言,此网页也会发生这种情况,无论是在窗口本身上单击还是在选定窗口的情况下按下按键时。
我的基本代码如下所示,其中 click(...)
通常包含坐标作为参数,但为了简单起见,它们被省略。在本例中,0 结束程序,并且有三个选项可供选择,数字为 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(...)
下面的尝试尝试实现@Sanju的建议,首先是在线程内的整个while,然后是队列
,两者都没有按预期工作......
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()
另一种尝试使用 PyHook,但仍然面临上述问题。
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()
最佳答案
您所需要的就是将您的点击部分移动到线程并使用可共享对象(例如队列)共享用户输入。这听起来有点大材小用,但这就是让你的任务保持在后台的方法。
顺便说一句,Python 中有许多可用的 GUI 应用程序框架,例如 tkinter、wxpython,它们可以简化您的目标。
关于python - 在 Windows 后台根据键盘记录器输入运行 Python Clicker,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30829028/