简体   繁体   English

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

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

I've written a simple program which allows you to record click events and save them. 我编写了一个简单的程序,可让您记录点击事件并保存。 You can then load the save again, and it will fire all the click events again as you saved them. 然后,您可以再次加载保存,保存时,它将再次触发所有单击事件。 For the folks wondering, I wrote this program a year ago for learning purposes. 令我惊讶的是,我一年前写这个程序是为了学习。 It worked perfectly then. 那时,它工作得很好。 I wanted to use it today again, but it doesn't run properly anymore. 我今天想再次使用它,但是现在无法正常运行了。

I launch the program, and select option 1 which calls the selectAndSavePoints method. 我启动程序,然后选择选项1,该选项调用selectAndSavePoints方法。 It waits till I press the key s to start, and then proceeds to monitor click events. 它一直等到我按键s才开始,然后继续监视单击事件。 The problem is, that it blocks them off. 问题是,它阻止了它们。 I can see that the position of the click event is written in the console, but when I as example click on my explorer icon in the task-bar to open it, it doesn't open because the click event is being hijacked instead of monitored and allowed to pass through to the Windows operating system. 我可以看到click事件的位置是在控制台中编写的,但是当我作为示例单击任务栏上的资源管理器图标以将其打开时,它没有打开,因为click事件被劫持而不是受到监视并允许传递到Windows操作系统。

I tried fixing this by copying my click method in the loadAndExecutePoints method and placing it inside the MonitorMouseClicks method above the declaration of the global coordsToClick variable. 我尝试通过在loadAndExecutePoints方法中复制我的click方法并将其放置在全局coordsToClick变量的声明上方的MonitorMouseClicks方法中来解决此问题。 I'd then inside the onclick method call the click method to manually click it again. 然后,我将在onclick方法内部调用click方法以再次手动单击它。 When I run this, it registers the first click, I can see it logged again, and then the program should manually click it for me, but the process then hangs. 当我运行它时,它会注册第一次单击,我可以看到它再次被记录下来,然后程序应该为我手动单击它,但是过程挂起。 Pressing alt + f4, ctrl + break or taskkilling the program doesn't work then. 然后按alt + f4,ctrl + break或对程序进行任务杀死无法正常工作。 I have to restart my computer for the command line window to be gone. 我必须重新启动计算机才能使命令行窗口消失。 I have no clue what is happening over here. 我不知道这里发生了什么。

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()

I hope to be able to find someone here who can help me figure out why this application has stopped working, what the exact problem is and how I can work around it or fix it. 我希望能够在这里找到可以帮助我弄清楚该应用程序为何停止工作,确切的问题是什么以及如何解决或修复它的人。 As you can see in the program, I use quite a lot imports. 如您在程序中所见,我使用了很多导入。 Most of them are default modules, but here are the instructions to get the modules which aren't default. 它们大多数是默认模块,但以下是获取非默认模块的说明。

pip install keyboard
pip install pywin32

The pyHook module can be downloaded here https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyhook . pyHook模块可以在这里https://www.lfd.uci.edu/~gohlke/pythonlibs/#pyhook下载。 I downloaded the pyHook‑1.5.1‑cp35‑cp35m‑win_amd64.whl file which you can then install by using this command 我下载了pyHook‑1.5.1‑cp35‑cp35m‑win_amd64.whl文件,然后可以使用此命令进行安装

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

I am using python 3.5.4 by the way. 我正在使用python 3.5.4。

You need to set the return values of onKeyboardEvent ( MonitorKeyPresses ) and onMouseEvent ( MonitorMouseClicks ) to True , which is a normal call, and if it is False , the event will be intercepted. 你需要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

(BTW, You don't need to restart the computer. The right button is not blocked. You can right-click the console and right-click close.) (顺便说一句,您不需要重新启动计算机。右键没有被阻止。您可以右键单击控制台,然后右键单击关闭。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM