2010-04-29 9 views
52

¿Es posible simular las acciones de un mouse desde un programa en OS X? Específicamente, la versión corta es que estoy tratando de simular una pantalla táctil usando dos cámaras web. Entonces, suponiendo que pueda obtener las posiciones X, Y, ¿puedo enviar información al sistema operativo como un movimiento del mouse o hacer clic?Simulación de entrada de mouse mediante programación en OS X

Editar- O si es particularmente fácil en otro sistema operativo estaría dispuesto a considerar eso.

+0

Dependiendo de su caso de uso, hay una Instrumento llamado "Grabador UI" que registra todo lo que haces en la interfaz de usuario de tu programa y lo reproduce cuando lo desees. – zneak

+0

Gracias, pero lo que realmente quiero hacer es enviar cualquier entrada de mouse arbitraria al sistema operativo. –

+3

Lo hice antes al ejecutar un servidor vnc y escribir un pequeño cliente vnc para enviar eventos del mouse al servidor. Hay servidores vnc de código abierto que hacen eso, así que un último recurso sería leer la fuente de uno. –

Respuesta

82

Sí, es posible. Puede usar el Quartz Event Services para simular eventos de entrada.

Suponiendo C, escribí esto rápido ejemplo:

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

int main() { 
    // Move to 200x200 
    CGEventRef move1 = CGEventCreateMouseEvent(
     NULL, kCGEventMouseMoved, 
     CGPointMake(200, 200), 
     kCGMouseButtonLeft // ignored 
    ); 
    // Move to 250x250 
    CGEventRef move2 = CGEventCreateMouseEvent(
     NULL, kCGEventMouseMoved, 
     CGPointMake(250, 250), 
     kCGMouseButtonLeft // ignored 
    ); 
    // Left button down at 250x250 
    CGEventRef click1_down = CGEventCreateMouseEvent(
     NULL, kCGEventLeftMouseDown, 
     CGPointMake(250, 250), 
     kCGMouseButtonLeft 
    ); 
    // Left button up at 250x250 
    CGEventRef click1_up = CGEventCreateMouseEvent(
     NULL, kCGEventLeftMouseUp, 
     CGPointMake(250, 250), 
     kCGMouseButtonLeft 
    ); 

    // Now, execute these events with an interval to make them noticeable 
    CGEventPost(kCGHIDEventTap, move1); 
    sleep(1); 
    CGEventPost(kCGHIDEventTap, move2); 
    sleep(1); 
    CGEventPost(kCGHIDEventTap, click1_down); 
    CGEventPost(kCGHIDEventTap, click1_up); 

    // Release the events 
    CFRelease(click1_up); 
    CFRelease(click1_down); 
    CFRelease(move2); 
    CFRelease(move1); 

    return 0; 
} 

Y suponiendo GCC, compilar con:

gcc -o program program.c -Wall -framework ApplicationServices

disfrutar de la magia.

+2

Whoa, excelente respuesta a una vieja pregunta, ¡gracias! –

+0

@Rob: de nada. Espero que la respuesta no llegue demasiado tarde. – jweyrich

+0

funciona como un amuleto – piaChai

7

Si no quiere compilar cosas y está buscando una herramienta basada en shell, Cliclick puede ser la solución.

2

Aquí es un programa de trabajo C basado en la respuesta de jweyrick:

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

alojado en https://gist.github.com/Dorian/5ae010cd70f02adf2107

+2

Yo usaría 'usleep (duración * 1000000)'. De lo contrario, solo dormirás durante un número entero de segundos. – nneonneo

6

Swift mover el ratón y haga clic ejemplo:

func mouseMoveAndClick(onPoint point: CGPoint) { 
    guard let moveEvent = CGEvent(mouseEventSource: nil, mouseType: .mouseMoved, mouseCursorPosition: point, mouseButton: .left) else { 
     return 
    } 
    guard let downEvent = CGEvent(mouseEventSource: nil, mouseType: .leftMouseDown, mouseCursorPosition: point, mouseButton: .left) else { 
     return 
    } 
    guard let upEvent = CGEvent(mouseEventSource: nil, mouseType: .leftMouseUp, mouseCursorPosition: point, mouseButton: .left) else { 
     return 
    } 
    moveEvent.post(tap: CGEventTapLocation.cghidEventTap) 
    downEvent.post(tap: CGEventTapLocation.cghidEventTap) 
    upEvent.post(tap: CGEventTapLocation.cghidEventTap) 
} 
Cuestiones relacionadas