8

我有兴趣在不实际移动鼠标的情况下在 Mac OS X 上模拟鼠标单击事件/键盘敲击。

在 Windows 中,可以使用消息来执行此操作:

win32:模拟点击而不模拟鼠标移动?

Mac OS X 有类似的东西吗?我知道Quartz Event Services,但似乎该 API 只会限制我将事件发送到当前键窗口。这是真的?是否可以将键盘/鼠标事件发送到非键窗口?我真的只需要能够将键盘命令发送到另一个应用程序。

4

3 回答 3

6

我知道这是一个旧线程,但我想发布一个答案,以防万一有人偶然发现。

做到这一点的两种最佳方法实际上是完全独立于平台的。(除非您想使用 C,在我看来这不必要地冗长,但如果您想使用它,请参阅此答案

1)最简单的方法是使用javAuto。(注:javAuto 已移至此处)。它几乎是一个可以跨平台编译和运行基本自动化脚本的 java 程序。要模拟鼠标点击,您可以使用以下命令:

mouseClick(button, x, y);

要在不移动鼠标的情况下模拟 mouseClick,您可以使用以下命令:

// 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,这将比 javaAuto 中的相同进程涉及更多代码。

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());
        }
    }
}
于 2014-02-10T18:45:52.330 回答
6

这是一个工作 C 程序,用于模拟坐标 (X,Y) 处的 N 次点击:

// 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

于 2015-11-14T00:22:47.560 回答
0

您可以使用 NSEvent、CGEvent 或 Accessibility API 来完成此操作。诀窍是,如果它不是最前面的应用程序,您通常需要首先激活要单击的应用程序。然后,您只需单击屏幕坐标中的一个点。

于 2015-05-15T11:14:59.890 回答