首页 > 解决方案 > 模拟鼠标按下窗口(有效,但位置不起作用)

问题描述

我正在用python编写代码来模拟鼠标按下窗口。我目前的代码是:

def MousePress_Pos(x, y):
    pos = MAKELONG(x, y)
    SendMessage(hwnd, WM_LBUTTONDOWN, MK_LBUTTON, pos)
    SendMessage(hwnd, WM_LBUTTONUP, MK_LBUTTON, pos)

这段代码成功地模拟了鼠标按下,但它没有在给定的 X 和 Y 上执行此操作。相反,它按下了我鼠标的当前 X 和 Y!

当窗口没有聚焦时也会发生这种情况。它只是忽略给定的 X 和 Y 并用鼠标的 X 和 Y 按下窗口。

我不知道为什么会这样。有人知道我该怎么做吗?谢谢。

标签: pythonwinapi

解决方案


使用SendInput而不是SendMessage模拟鼠标输入。

以下是 C++ 中的示例,您可以参考:

int sx = GetSystemMetrics(SM_CXSCREEN);
int sy = GetSystemMetrics(SM_CYSCREEN);

long x_calc = x * 65536 / sx;
long y_calc = y * 65536 / sy;

INPUT mi = { 0 };
mi.type = INPUT_MOUSE;
mi.mi.dx = x_calc;
mi.mi.dy = y_calc;
mi.mi.dwFlags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE | MOUSEEVENTF_LEFTDOWN;

SendInput(1, &mi, sizeof(mi));

mi.mi.dwFlags = MOUSEEVENTF_LEFTUP;

SendInput(1, &mi, sizeof(mi));

如何在 Python 中实现相同的工作,请参考以下两个线程。

第一个

import math
#...
    x_calc = math.floor(65536 * x_pos / ctypes.windll.user32.GetSystemMetrics(self.SM_CXSCREEN) + 1)
    y_calc = math.floor(65536 * y_pos / ctypes.windll.user32.GetSystemMetrics(self.SM_CYSCREEN) + 1)

第二个

class MOUSEINPUT(ctypes.Structure):
    _fields_ = (("dx",          wintypes.LONG),
                ("dy",          wintypes.LONG),
                ("mouseData",   wintypes.DWORD),
                ("dwFlags",     wintypes.DWORD),
                ("time",        wintypes.DWORD),
                ("dwExtraInfo", wintypes.ULONG_PTR))

推荐阅读