Python脚本监视单击事件,但阻止它们,不允许单击事件通过

Python脚本监视单击事件,但阻止它们,不允许单击事件通过,python,winapi,python-3.5,pyhook,pythoncom,Python,Winapi,Python 3.5,Pyhook,Pythoncom,我已经编写了一个简单的程序,允许您记录点击事件并保存它们。然后,您可以再次加载保存,它将在您保存所有单击事件时再次激发这些事件。对于那些想知道的人来说,我一年前写这个程序是为了学习。当时它工作得很好。我今天想再次使用它,但它已经不能正常运行了 我启动程序,选择选项1,它调用selectAndSavePoints方法。它等待我按下s键开始,然后继续监视单击事件。问题是,它会阻止他们。我可以看到单击事件的位置写在控制台中,但当我在任务栏中单击我的资源管理器图标打开它时,它没有打开,因为单击事件被劫持

我已经编写了一个简单的程序,允许您记录点击事件并保存它们。然后,您可以再次加载保存,它将在您保存所有单击事件时再次激发这些事件。对于那些想知道的人来说,我一年前写这个程序是为了学习。当时它工作得很好。我今天想再次使用它,但它已经不能正常运行了

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

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

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()
pyHook模块可以在这里下载。我下载了pyHook‑1.5.1‑cp35‑cp35m‑win_amd64.whl文件,然后可以使用此命令安装该文件

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

顺便说一下,我正在使用python 3.5.4。

您需要将onKeyboardEvent
monitorkeypress
)和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

(顺便说一句,您不需要重新启动计算机。右键未被阻止。您可以右键单击控制台并右键单击关闭。)

谢谢您的回答。这确实是问题所在。我按照您的建议将return0更改为returntrue,从而解决了这个问题。当我尝试手动单击时,我也意识到了问题所在,它变得非常滞后:我在一个单击事件的事件处理程序中执行了一次单击,因此这导致了一个无限循环,导致了滞后的感觉。非常感谢吴德雷克,我真的很感谢你的回答!
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