Python 脚本监听点击事件但拦截,不让点击事件通过

Python script monitors click events but blocks them, not allowing the click event to pass through

我写了一个简单的程序,可以让你记录点击事件并保存它们。然后您可以再次加载保存,它会在您保存时再次触发所有点击事件。对于那些想知道的人,我一年前出于学习目的编写了这个程序。那时它工作得很好。我今天想再次使用它,但它不再 运行 正确。

我启动程序,select 选项 1 调用 selectAndSavePoints 方法。它等到我按下 s 键开始,然后继续监听点击事件。问题是,它阻止了他们。我可以看到点击事件的位置写在控制台中,但是当我在任务栏中点击我的资源管理器图标以打开它时,它不会打开,因为点击事件被劫持而不是被监控并允许传递到 Windows 操作系统。

我尝试通过在 loadAndExecutePoints 方法中复制我的 click 方法并将其放置在全局 coordsToClick 变量声明上方的 MonitorMouseClicks 方法中来修复此问题。然后我会在 onclick 方法中调用 click 方法再次手动单击它。当我 运行 这个时,它记录了第一次点击,我可以看到它再次记录,然后程序应该为我手动点击它,但过程随后挂起。然后按 alt + f4、ctrl + break 或 taskkilling 程序不起作用。我必须重新启动计算机才能使命令行 window 消失。我不知道这里发生了什么。

from keyboard import wait
from threading import Thread
from pythoncom import PumpMessages
from ctypes import windll
from pyHook import HookManager
from os import listdir
from win32api import mouse_event
from win32api import SetCursorPos
from win32con import MOUSEEVENTF_LEFTDOWN
from win32con import MOUSEEVENTF_LEFTUP
from time import sleep

coordsToClick = []

def sanitised_input(prompt, type_=None, min_=None, max_=None, range_=None, distinct_=False):
    if min_ is not None and max_ is not None and max_ < min_:
        raise ValueError("min_ must be less than or equal to max_.")
    while True:
        ui = input(prompt)
        if type_ is not None:
            try:
                ui = type_(ui)
            except ValueError:
                print("Input type must be {0}.".format(type_.__name__))
                continue
        if max_ is not None and ui > max_:
            print("Input must be less than or equal to {0}.".format(max_))
        elif min_ is not None and ui < min_:
            print("Input must be greater than or equal to {0}.".format(min_))
        elif range_ is not None and ui not in range_:
            if isinstance(range_, range):
                print("Input must be between {0.start} and {0.stop}.".format(range_))
            else:
                if len(range_) == 1:
                    print("Input must be {0}.".format(*range_))
                else:
                    print("Input must be {0}.".format(" or ".join((", ".join(map(str, range_[:-1])), str(range_[-1])))))
        elif distinct_ and not len(ui) == len(set(ui)):
            print("Input should only contain unique characters!")
        else:
            return ui

def selectAndSavePoints():
    print("Press the key 's' to start selecting points")
    print("Press the key 'p' to cancel last selected point, so previous action is undone. Does work multiple times")
    print("Once you're finished, press the key 'f' to save them")
    wait("s")
    def MonitorKeyPresses(_hookManager):
        global coordsToClick
        def onpress(event):
            if event.Key == "P":
                del coordsToClick[-1]
            return 0
        _hookManager.SubscribeKeyDown(onpress)
        _hookManager.HookKeyboard()
        PumpMessages()
    def MonitorMouseClicks(_hookManager):
        global coordsToClick
        def onclick(event):
            coordsToClick.append(event.Position)
            print(event.Position)
            return 0
        _hookManager.SubscribeMouseLeftDown(onclick)
        _hookManager.HookMouse()
        PumpMessages()
    hookManager = HookManager()
    threadClick = Thread(target = MonitorMouseClicks, args = (hookManager,))
    threadClick.start()
    threadPress = Thread(target = MonitorKeyPresses, args = (hookManager,))
    threadPress.start()
    wait('f')
    windll.user32.PostQuitMessage(0)
    hookManager.UnhookMouse()
    hookManager.UnhookKeyboard()
    filename = input("Enter the filename: ")
    file = open("../Saves/" + filename + ".txt", 'w')
    for coords in coordsToClick:
        file.write(str(coords[0]) + ":" + str(coords[1]) + "\n")
    file.close()


def loadAndExecutePoints():
    def click(x, y):
        SetCursorPos((x, y))
        mouse_event(MOUSEEVENTF_LEFTDOWN,x,y,0,0)
        mouse_event(MOUSEEVENTF_LEFTUP,x,y,0,0)
    files = listdir("../Saves")
    for i in range(len(files)):
        print("[" + str(i) + "]: " + files[i])
    filenumber = sanitised_input("Enter the file mumber: ", type_=int, range_=range(len(files)))
    filename = files[filenumber]
    print("Press 's' to start executing the clicks")
    wait('s')
    lines = [line.rstrip('\n') for line in open('../Saves/' + filename)]
    for line in lines:
        components = line.split(":")
        click(int(components[0]), int(components[1]))
        sleep(0.2)

def main():
    print("Select a option")
    print("[1]: Select and Save Points")
    print("[2]: Load and Execute Points")
    option = sanitised_input("", type_=int, range_=(1, 2))
    if(option == 1):
        selectAndSavePoints()
    else:
        loadAndExecutePoints()

while(True):
    main()

我希望能够在这里找到可以帮助我弄清楚此应用程序停止工作的原因、确切问题是什么以及我如何解决或修复它的人。正如您在程序中看到的,我使用了相当多的导入。其中大部分是默认模块,但这里是获取非默认模块的说明。

pip install keyboard
pip install pywin32

pyHook 模块可以在这里下载https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyhook。我下载了 pyHook‑1.5.1‑cp35‑cp35m‑win_amd64.whl 文件,然后您可以使用此命令安装该文件

pip install pyHook‑1.5.1‑cp35‑cp35m‑win_amd64.whl

顺便说下我用的是python3.5.4

您需要设置 onKeyboardEvent(MonitorKeyPresses) 和 onMouseEvent(MonitorMouseClicks)到True,是正常调用,如果是False,事件会被拦截。

def MonitorKeyPresses(_hookManager):
    global coordsToClick
    def onpress(event):
        if event.Key == "P":
            del coordsToClick[-1]
        return True
...

def MonitorMouseClicks(_hookManager):
    global coordsToClick
    def onclick(event):
        coordsToClick.append(event.Position)
        print(event.Position)
        return True

(顺便说一句,你不需要重启电脑,右键没有被挡住,你可以右击控制台,右击关闭。)