如何在Cocoa中编程模拟鼠标单击而无需移动鼠标

9

我想在Mac OS X上模拟鼠标点击事件/键盘按键,而不实际移动鼠标。

在Windows中,可以使用消息来实现此操作:

win32: simulate a click without simulating mouse movement?

在Mac OS X中是否有类似功能的工具?我知道Quartz Event Services,但似乎该API只能将事件发送到当前活动窗口。这是真的吗?是否可以向非活动窗口发送键盘/鼠标事件?我只需要能够向其他应用程序发送键盘命令即可。


可能是在OS X中以编程方式模拟鼠标输入的重复问题。 - John Calsbeek
1
我可能错了,但我认为你的问题主要在于应用程序本身选择哪个窗口响应事件。换句话说,不会有任何操作系统级别的API来完成这个任务。我建议尝试通过AppleScript和System Events套件来实现 - 如果可以这样做,那么你就可以以编程方式完成它。否则,这可能会非常困难。 - John Calsbeek
1
请查看CGEventPostToPSN。 - Raviprakash
3个回答

6

下面是一个能够模拟在坐标(X,Y)上进行N次点击的C程序:

// Compile instructions:
//
// gcc -o click click.c -Wall -framework ApplicationServices

#include <ApplicationServices/ApplicationServices.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
  int x = 0, y = 0, n = 1;
  float duration = 0.1;

  if (argc < 3) {
    printf("USAGE: click X Y [N] [DURATION]\n");
    exit(1);
  }

  x = atoi(argv[1]);
  y = atoi(argv[2]);

  if (argc >= 4) {
    n = atoi(argv[3]);
  }

  if (argc >= 5) {
    duration = atof(argv[4]);
  }

  CGEventRef click_down = CGEventCreateMouseEvent(
    NULL, kCGEventLeftMouseDown,
    CGPointMake(x, y),
    kCGMouseButtonLeft
  );

  CGEventRef click_up = CGEventCreateMouseEvent(
    NULL, kCGEventLeftMouseUp,
    CGPointMake(x, y),
    kCGMouseButtonLeft
  );

  // Now, execute these events with an interval to make them noticeable
  for (int i = 0; i < n; i++) {
    CGEventPost(kCGHIDEventTap, click_down);
    sleep(duration);
    CGEventPost(kCGHIDEventTap, click_up);
    sleep(duration);
  }

  // Release the events
  CFRelease(click_down);
  CFRelease(click_up);

  return 0;
}

托管在https://gist.github.com/Dorian/5ae010cd70f02adf2107


6

我知道这是一个旧帖子了,但我想发表一个答案,以防有人偶然发现。

实际上,有两种最好的方法完全跨越平台。 (除非你想使用C语言,但在我看来,这样做太冗长了,但如果你想使用,可以看看这个答案)

1) 最简单的方法是使用javAuto。(注意: javAuto已经移到这里). 这基本上是一个Java程序,可以编译和运行基本的自动化脚本,跨平台。要模拟鼠标单击,可以使用这个命令:

mouseClick(button, x, y);

要模拟一个不移动鼠标的鼠标单击,可以使用以下命令:

// get cursor coordinates
int cPos[] = cursorGetPos();

// mouse click at the coordinates you want
mouseClick("left", x, y);

// instantly move the mouse back
mouseMove(cPos[0], cPos[1]);

鉴于mouseClick和mouseMove命令不涉及任何中间鼠标移动,因此单击将在(x,y)处发生,但鼠标不会移动。

2) 下一个最好的方法是使用普通的Java,这将需要比javAuto中相同过程更多的代码。

import java.awt.*;
import java.awt.event.InputEvent;

public class example {
    public static void main(String[] args) {
        //get the current coordinates
        PointerInfo a = MouseInfo.getPointerInfo();
        Point b  = a.getLocation();
        int xOrig = (int)b.getX();
        int yOrig = (int)b.getY();

        try {
            //simulate a click at 10, 50
            Robot r = new Robot();
            r.mouseMove(10, 50);
            r.mousePress(InputEvent.BUTTON1_MASK); //press the left mouse button
            r.mouseRelease(InputEvent.BUTTON1_MASK); //release the left mouse button

            //move the mouse back to the original position
            r.mouseMove(xOrig, yOrig);
        } catch (Exception e) {
            System.out.println(e.toString());
        }
    }
}

1
我不再参与这个项目了,但是说真的,太棒了!我相信这将来会帮助很多人 :) - Dany Joumaa
@John 你知道如何使用javAuto确定是否执行了点击操作吗?此外,javAuto能够导入吗? - thetypist
1
@thetypist 它肯定可以导入,但我几乎确定没有办法检测到Java中是否执行了单击操作,因为它运行在JVM上,而不是连接到操作系统。我认为检测鼠标单击是你想使用C语言并且必须依赖于平台的事情。 - John Dorian
1
那些 JavAuto 的链接已经失效了。现在可以在这里找到:https://github.com/Javauto - Jayden Lawson

0
你可以使用 NSEvent、CGEvent 或 Accessibility APIs 来实现这个功能。诀窍是,如果要点击的应用程序不是最前面的应用程序,首先通常需要将其激活。然后,只需在屏幕坐标上点击一个点即可。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接