【问题标题】:How can I accurately program an automated "click" on Windows?如何在 Windows 上准确地编写自动“点击”程序?
【发布时间】:2010-11-03 22:49:43
【问题描述】:

我使用MOUSE_DOWNMOUSE_UP 编写了一个程序,使用Win32 在预定时间自动单击应用程序。它通常效果很好,只是我发现我需要放入一个

sleep 0.1

MOUSE_DOWNMOUSE_UP 之间。 (使用 Ruby,它可以让您睡一小会儿)。

没有睡眠,有时点击无法通过。但我注意到有时,点击“太长”。点击实际上是在 Flash 应用程序的右箭头上。这个右箭头将转到列表中的下一个项目。因此,如果您MOUSE_DOWN 稍长一点,它实际上会移动 2 或 3 个项目,而不仅仅是 1 个项目。

所以我想知道,在这种情况下,有没有办法准确模拟 1 次点击。可能没有MOUSE_CLICK 事件?必须用MOUSE_DOWNMOUSE_UP模拟?

(在Win32上它实际上被称为MOUSEEVENTF_LEFTDOWNMOUSEEVENTF_LEFTUP,为了简单起见,它被称为MOUSE_DOWN。)

【问题讨论】:

  • 鉴于您保留了 [perl] 标签,我不得不问我对您之前关于此问题的回答中的哪一部分不能解决您的问题:stackoverflow.com/questions/1007391/…
  • 我开始使用 Win32:GUI 但它需要更多的安装,所以我开始研究 Ruby。 Win32:GuiTest 也需要安装吗?如果是点击,那可能会更好。它是否使用时间戳将点击作为 MOUSE_DOWN 和 MOUSE_UP 分开一段时间?
  • @Jian Lin 查看源代码,似乎立即发送一个鼠标按下事件,然后是一个鼠标向上事件(在同一位置),中间没有延迟。我想当我发表关于延迟的评论时,我正在考虑双击。 Win32::GuiTest 也需要安装。

标签: python ruby perl winapi windows


【解决方案1】:

您无法决定鼠标按下和鼠标抬起之间的延迟设置会导致有效的单击,操作系统会决定。

没有sleep函数可以保证你想要的鼠标按下和鼠标抬起事件之间的时间。 Perl 的Win32::GuiTest 模块允许您发送实际的单击事件,而不是弄乱向下和向上事件的时间。 稍后:查看源代码,Win32::GuiTest 似乎只是触发鼠标向下和向上事件,它们之间没有任何延迟see GuiTest.pm

elsif ( $item =~ /leftclick/i ) {
    SendLButtonDown ();
    SendLButtonUp ();
}

此外,http://msdn.microsoft.com/en-us/library/ms646260(VS.85).aspx 声明 mouse_event 已被 SendInput http://msdn.microsoft.com/en-us/library/ms646310(VS.85).aspx 取代,这允许您发送带有时间戳等的 MOUSEINPUT 事件。

【讨论】:

  • Flash 应用是否仍然可以使点击时间比平时更长并移动 2 个项目?
【解决方案2】:

如果您不受特定语言的限制,您可以查看AutoIt,它专为此类事情而设计。 我在自动化鼠标点击或击键等操作方面有很好的经验。

【讨论】:

    【解决方案3】:

    我猜两件事:

    1. 我敢打赌 ruby​​ 不会也不能保证 sleep 0.1 真的只睡 0.1 秒。因为这可能不受 ruby​​s 控制和操作系统控制
    2. 通过 Win32 本身调用 Win32 API 可能需要任意时间并导致延迟

    【讨论】:

      【解决方案4】:

      既然 Windows API 支持低至 1 毫秒的睡眠时间,为什么不缩短睡眠时间呢? 0.01秒应该够了吧?

      【讨论】:

      • 我想我已经看到了 0.01 可能无法注册为点击的情况......但我可以尝试更多
      【解决方案5】:

      我会使用 AutoHotKey。它是开源和免费的,已经存在很长时间并积极维护,以至于其他人已经为它构建了一个 IDE。我用它来为表单测试生成独特的随机测试数据,但它也可以做鼠标操作。

      http://www.autohotkey.com/

      【讨论】:

        【解决方案6】:

        你用什么函数来完成这个?

        我希望SendInput 在 MOUSEINPUT 结构中传递 2 个链(一个按钮向下,另一个按钮向上)会为您完成此任务。您甚至可以使用伪造事件的时间戳来玩游戏,以获得比使用 sleep() 获得的更具确定性的行为。

        没有 CLICK 发送,因为应用程序负责将低级事件(鼠标移动、按下按钮、按下按钮、按下键、按下键等)折叠为“用户级”事件。


        一些代码,澄清一下。这是直接未经测试/编译的 C(阅读:糟糕的 C),但我希望它能说明我的观点。

        LPINPUT events = (LPINPUT)malloc(sizeof(INPUT) * 2);
        
        events[0].type = INPUT_MOUSE;
        events[0].mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
        events[0].mi.time = 0; //Here, you can play with timestamps (milliseconds)
        events[1].type = INPUT_MOUSE;
        events[1].mi.dwFlags = MOUSEEVENTF_LEFTUP;
        events[1].mi.time = 0; //Likewise
        
        //Push both events into the event queue
        SendInput(2, events, sizeof(INPUT));
        

        我的 Ruby 经验为零,所以我不知道您将如何为您的案例进行互操作。

        【讨论】:

        • 我使用 mouse_event = user32 'mouse_event' , ['L' , 'L' , 'L' , 'L' , 'L' ], 'V' 然后 mouse_event.call MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0 发送事件...如何使用时间戳而不是使用睡眠?
        • 添加了一些代码来说明我将如何尝试在 C 中执行此操作。它完全未经测试,但希望有所帮助。
        猜你喜欢
        • 1970-01-01
        • 2021-05-22
        • 1970-01-01
        • 2014-02-01
        • 2016-05-03
        • 1970-01-01
        • 1970-01-01
        • 2010-10-28
        • 2021-10-05
        相关资源
        最近更新 更多