2010-04-29 9 views
52

Est-il possible de simuler les actions d'une souris à partir d'un programme sous OS X? Plus précisément, la version courte est que j'essaie de simuler un écran tactile en utilisant deux webcams. Donc, en supposant que je peux obtenir X, positions Y, puis-je envoyer des informations à l'OS comme un mouvement de la souris ou cliquez sur? Edit - Ou si c'est particulièrement facile dans un autre système d'exploitation, je serais prêt à considérer cela.Simulation de l'entrée de la souris par programme sous OS X

+0

En fonction de votre cas d'utilisation, il y a une Instrument appelé "UI Recorder" qui enregistre tout ce que vous faites à l'interface utilisateur de votre programme et le relit quand vous le souhaitez. – zneak

+0

Merci, mais ce que je veux vraiment faire est d'envoyer n'importe quelle entrée de souris arbitraire au système d'exploitation. –

+3

Je l'ai fait auparavant en exécutant un serveur vnc et en écrivant un petit client vnc pour envoyer des événements de souris au serveur. Il existe des serveurs vnc open source qui font cela, donc un bon dernier recours serait de lire la source d'un. –

Répondre

82

Oui, c'est possible. Vous pouvez utiliser Quartz Event Services pour simuler des événements d'entrée.

En supposant C, j'ai écrit cet exemple rapide:

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

Et en supposant GCC, compilez avec:

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

Profitez de la magie.

+2

Whoa, bonne réponse à une vieille question, merci! –

+0

@Rob: de rien. J'espère que la réponse n'est pas arrivée trop tard. – jweyrich

+0

fonctionne comme un charme – piaChai

7

Si vous ne voulez pas compiler des choses et que vous cherchez un outil basé sur un shell, Cliclick peut être la solution.

2

Voici un programme C de travail basé sur la réponse de jweyrick:

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

+2

J'utiliserais 'usleep (durée * 1000000)'. Sinon, vous ne dormirez que pendant un nombre entier de secondes! – nneonneo

6

Swift déplacement de la souris et cliquez par exemple:

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) 
}