Search code examples
python-3.xwinapipyautogui

Python - win32api cursor script that automatically moves a cursor, clicks and brings it back


I have a script that detects mouse clicks. I need it to : [1. Move my cursor to a position 2. Click on that position 3. Move it back to the original position] and that will run whenever I click anywhere on the screen. The problem is, the click that script created is still registered and creates a loop back and forth. How can I change this behaviour, so it doesn't run the function when the click happens from the script, not from me?

import win32api
import time

state_left = win32api.GetAsyncKeyState(0x01)  # LMB down is 0 or 1, LMB up is -127 or -128

time.sleep(2)
while True:
    a = win32api.GetAsyncKeyState(0x01)
    if a != state_left:
        state_left = a
        print(a)
        if a < 0:
            print('Left Button Pressed')
        else:
            print('Left Button Released')```

Solution

  • According to the document, you can use GetAsyncKeyState:

    The GetAsyncKeyState function works with mouse buttons. However, it checks on the state of the physical mouse buttons, not on the logical mouse buttons that the physical buttons are mapped to. For example, the call GetAsyncKeyState(VK_LBUTTON) always returns the state of the left physical mouse button, regardless of whether it is mapped to the left or right logical mouse button. You can determine the system's current mapping of physical mouse buttons to logical mouse buttons by calling GetSystemMetrics(SM_SWAPBUTTON).

    Therefore, it will only be triggered when the mouse is changed in physical state, which can make the program work normally.

    The reason for the two triggers is that the value of a is set incorrectly. You only need to get the highest bit of the mouse state through the GetAsyncKeyState function, as shown in the following code:

    c = 1
    state_left = win32api.GetAsyncKeyState(0x01)  # LMB down is 0 or 1, LMB up is -127 or -128
    
    while True:
        a = win32api.GetAsyncKeyState(0x01) & 0x8000
        if a != state_left:
            state_left = a
            print(a)
            if a != 0:
                print('Left Button Pressed')
            else:
                print('Left Button Released')
                before = win32api.GetCursorPos()
                win32api.SetCursorPos((1300, 900))
    
                pyautogui.click()
                win32api.SetCursorPos(before)
    
        time.sleep(0.001)
    

    More reference: What are these numbers in the code GetAsyncKeyState(VK_SHIFT) & 0x8000 ? Are they essential?