简体   繁体   English

python win32api MOUSEEVENTF_MOVE 未按预期工作

[英]python win32api MOUSEEVENTF_MOVE not working as expected

Here is the code这是代码

# set mouse position to absolute position 674, 499
win32api.SetCursorPos((674, 499))
# add 100 to current x position which will be 674 + 100 = 774
# will not change y position it will be 499 
win32api.mouse_event(win32con.MOUSEEVENTF_MOVE, 100 ,0)
# print the position
print(f'The final position is {win32api.GetCursorPos()}')

I ran the code in a loop for a while and Here is the output:我在循环中运行了一段时间的代码,这是 output:

The final position is (864, 499)
The final position is (983, 499)
The final position is (984, 499)
The final position is (983, 499)
The final position is (984, 499)
The final position is (983, 499)
The final position is (983, 499)
The final position is (984, 499)
The final position is (983, 499)
The final position is (984, 499)
The final position is (983, 499)
The final position is (983, 499)
The final position is (984, 499)
The final position is (983, 499)
The final position is (984, 499)
The final position is (983, 499)
The final position is (864, 499)
The final position is (864, 499)
The final position is (882, 499)
The final position is (864, 499)
The final position is (984, 499)

In the running of the script, I did not move my mouse(my hand is not holding my mouse during the script is running)在脚本运行中,我没有移动鼠标(脚本运行期间我的手没有握住鼠标)

In my understanding, the output will always be (774, 499), but it gives me a surprise without a warning, it is because of my wrong understanding of the method or it`s related to something else?在我的理解中,output 永远是(774, 499),但它给了我一个毫无预兆的惊喜,是因为我对方法的理解错误还是与其他事情有关? please help.请帮忙。 Thank you all.谢谢你们。

[MS.Docs]: mouse_event function (winuser.h) which states: [MS.Docs]:mouse_event function (winuser.h)其中指出:

Note This function has been superseded.注意此 function 已被取代。 Use SendInput instead.请改用SendInput

also contains details on how to pass those values in the Remarks section.还包含有关如何在备注部分传递这些值的详细信息。

Options (to move the mouse relative to current position):选项(相对于当前位置移动鼠标):

  1. Since you're already using GetCursorPos / SetCursorPos , you could:由于您已经在使用GetCursorPos / SetCursorPos ,您可以:

    • Get current position获取当前 position

    • Add deltas添加增量

    • Set the new position设置新 position

    This makes most sense from what I am concerned从我所关心的情况来看,这是最有意义的

  2. Use SendInput .使用发送输入 But PyWin32 doesn't wrap it, so you'd need to call it via CTypes , but that requires some deeper knowledge ( C , Python internals, WinAPI ), and also requires lots of boilerplate code.但是PyWin32没有包装它,所以你需要通过CTypes调用它,但这需要一些更深入的知识( CPython内部, ZA05B798442A1AF567F798BC01样板代码)和EBA01。 [SO]: How to wrap the SendInput function to python using ctypes is exactly about that [SO]:如何使用 ctypes 将 SendInput function 包装到 python就是这样

  3. Use other 3 rd -party modules.使用其他第3方模块。 With [PyPI]: pynput you can accomplish this in a couple lines of code.使用[PyPI]: pynput ,您可以在几行代码中完成此操作。 Probably PyWinAuto is another candidate可能PyWinAuto是另一个候选者

  4. Continue digging in mouse_event direction (although I consider it pointless)继续向mouse_event方向挖掘(尽管我认为这毫无意义)

code00.py代码00.py

#!/usr/bin/env python

import msvcrt
import random
import sys
import time

import win32con as wcon
import win32api as wapi
import win32gui as wgui


def transform_relative(val, tres0, tres1, acc, speed):
    ret = val
    val = abs(val)
    if val > tres0 and acc:
        ret *= 2
    if val > tres1 and acc == 2:
        ret *= 2
    return round(ret * speed / 10)


def set_pos_mouse_event(x, y, absolute_coordinates=True):
    flags = wcon.MOUSEEVENTF_MOVE
    if absolute_coordinates: 
        flags |= wcon.MOUSEEVENTF_ABSOLUTE
        normx = round(x * 0xFFFF / (wapi.GetSystemMetrics(wcon.SM_CXSCREEN) - 1))
        normy = round(y * 0xFFFF / (wapi.GetSystemMetrics(wcon.SM_CYSCREEN) - 1))
    else:  # @TODO - cfati: Not working yet!!!
        tres0, tres1, acc = wgui.SystemParametersInfo(wcon.SPI_GETMOUSE)
        speed = wgui.SystemParametersInfo(wcon.SPI_GETMOUSESPEED)
        #print(tres0, tres1, acc, speed)
        normx = transform_relative(x, tres0, tres1, acc, speed)
        normy = transform_relative(y, tres0, tres1, acc, speed)
    print(f"Move with: ({x}, {y}) ({normx}, {normy})")
    wapi.mouse_event(flags, normx, normy)


def set_pos_cursor_pos(x, y, absolute_coordinates=True):
    print(f"Move with: ({x}, {y})")
    if absolute_coordinates:
        wapi.SetCursorPos((x, y))
    else:
        curx, cury = wapi.GetCursorPos()
        wapi.SetCursorPos((curx + x, cury + y))


def main(*argv):
    maxx = wapi.GetSystemMetrics(wcon.SM_CXSCREEN) - 1
    maxy = wapi.GetSystemMetrics(wcon.SM_CYSCREEN) - 1
    #print(maxx, maxy)
    abs_coords = 0
    set_pos = set_pos_cursor_pos
    #set_pos = set_pos_mouse_event
    print(f"Using function: {set_pos.__name__}")
    print(f"Absolute coordinates: {'True' if abs_coords else 'False'}")
    print(f"Start position: {wapi.GetCursorPos()}")
    while not msvcrt.kbhit():
        print()
        #set_pos_mouse_event(100, 100, 1)
        #print(f"{wapi.GetCursorPos()}")
        x = random.randint(0, maxx)
        y = random.randint(0, maxy)
        if not abs_coords:
            curx, cury = wapi.GetCursorPos()
            x -= curx
            y -= cury
        set_pos(x, y, absolute_coordinates=abs_coords)
        print(f"Final position: {wapi.GetCursorPos()}")
        time.sleep(0.5)


if __name__ == "__main__":
    print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")),
                                                   64 if sys.maxsize > 0x100000000 else 32, sys.platform))
    rc = main(*sys.argv[1:])
    print("\nDone.")
    sys.exit(rc)

Notes :备注

  • I chose #1.我选择了#1。 ( set_pos_cursor_pos ). ( set_pos_cursor_pos )。 It works fine它工作正常

  • I also attempted #4.我也尝试了#4。 ( set_pos_mouse_event ) ( set_pos_mouse_event )

    • I was only able to complete half ( MOUSEEVENTF_ABSOLUTE ).我只能完成一半( MOUSEEVENTF_ABSOLUTE )。 I tried to complete the other half (that you are interested in) by implementing the steps from the URL (in transform_relative ) but it doesn't work我尝试通过执行URL (在transform_relative中)中的步骤来完成另一半(您感兴趣),但它不起作用
  • I chose concept clarity over common sense (performance).我选择概念清晰而不是常识(性能)。 Some API s ( GetSystemMetrics for example) are called from within functions that are executed lots of times.一些API (例如GetSystemMetrics )是从多次执行的函数中调用的。 That makes no sense, for production code they should be only called once (at the beginning) and the returned values passed as arguments to the function that needs them这是没有意义的,对于生产代码,它们应该只被调用一次(在开始时),并且返回的值作为 arguments 传递给需要它们的 function

Output (2 variants that work): Output (2 个有效的变体):

 [cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q073428381]> "e:\Work\Dev\VEnvs\py_pc064_03.09_test0\Scripts\python.exe"./code00.py Python 3.9.9 (tags/v3.9.9:ccb0e6a, Nov 15 2021, 18:08:50) [MSC v.1929 64 bit (AMD64)] 064bit on win32 Using function: set_pos_cursor_pos Absolute coordinates: False Start position: (583, 610) Move with: (-461, 103) Final position: (122, 713) Move with: (44, -324) Final position: (166, 389) Move with: (1153, 418) Final position: (1319, 807) Move with: (390, 118) Final position: (1709, 925) Move with: (-860, 127) Final position: (849, 1052) Move with: (127, -202) Final position: (976, 850) Move with: (-84, -605) Final position: (892, 245) Move with: (86, 330) Final position: (978, 575) Move with: (-167, 170) Final position: (811, 745) Move with: (-63, -233) Final position: (748, 512) Done. [cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q073428381]> "e:\Work\Dev\VEnvs\py_pc064_03.09_test0\Scripts\python.exe"./code00.py Python 3.9.9 (tags/v3.9.9:ccb0e6a, Nov 15 2021, 18:08:50) [MSC v.1929 64 bit (AMD64)] 064bit on win32 Using function: set_pos_mouse_event Absolute coordinates: True Start position: (748, 512) Move with: (1076, 803) (36746, 48772) Final position: (1076, 803) Move with: (1435, 572) (49006, 34741) Final position: (1435, 572) Move with: (197, 820) (6728, 49804) Final position: (197, 820) Move with: (1153, 522) (39376, 31705) Final position: (197, 820) Move with: (12, 29) (410, 1761) Final position: (12, 29) Move with: (150, 176) (5123, 10690) Final position: (150, 176) Move with: (882, 37) (30121, 2247) Final position: (882, 37) Move with: (582, 195) (19876, 11844) Final position: (582, 195) Move with: (1066, 810) (36405, 49197) Final position: (1066, 810) Move with: (1888, 487) (64476, 29579) Final position: (1888, 487) Done.

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

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