NSEvent et le clic de souris...

iShadowiShadow Membre
04:54 modifié dans API AppKit #1
Bonjour !
Je voudrais savoir comment simuler un clic de souris sur n'importe quelle zone de l'écran...
En regardant la doc Apple sur NSEvent, je vois cette methode :

+ (NSEvent *)mouseEventWithType:(NSEventType)type location:(NSPoint)location modifierFlags:(unsigned int)flags timestamp:(NSTimeInterval)time windowNumber:(int)windowNum context:(NSGraphicsContext *)context eventNumber:(int)eventNumber clickCount:(int)clickNumber pressure:(float)pressure


Je suppose donc que c'est celle qui qui va m'aider...

Voici le code que j'ai testé :

NSPoint tempPoint;<br />	tempPoint.x = 100;<br />	tempPoint.y = 50;<br />	NSEvent *tempEvent = [NSEvent mouseEventWithType:NSLeftMouseDown location:tempPoint modifierFlags:nil timestamp:1.0 windowNumber:1 context:nil eventNumber:1 clickCount:1 pressure:1.0];


Mais celui-ci n'a pas l'air de bien marcher... D'où mon topic.
En effet, que dois-je faire ? Est-ce-que il faut "lancer" l'Event ou cette méthode l'exécute automatiquement... De plus, dans la doc Apple, je vois ces arguments : timestamp et eventNumber, mais je n'arrive pas à  comprendre à  quoi ils servent...
Enfin, je veux spécifier dans windowNumber, non pas une fenetre spéciale, mais tout l'écran... Que faire ?

Merci d'avance  :)

Réponses

  • AliGatorAliGator Membre, Modérateur
    04:54 modifié #2
    Un NSEvent n'est qu'une classe "container"
    C'est juste un wrapper pour encapsuler toutes les données relatives à  l'event
    (c'est un peu comme une struct en C si tu veux, si je peux me permettre la comparaison un peu poussive)

    Donc en gros c'est bien beau tu as créé ton NSEvent, mais maintenant il faut l'envoyer à  un objet !
    Maintenant à  savoir lequel et comment, je te laisse chercher :D
  • iShadowiShadow Membre
    04:54 modifié #3
    LOL... alors là ...  :o
    Je comprend ce que représente à  présent un NSEvent en tant que conteneur... Mais pour l'envoyer à  un objet... Quel type d'objet d'abord, en fait ? Tout ce que je veux faire, c'est pouvoir simuler un clic de souris à  un endroit précis de l'écran... Que dois-je faire dans ce cas-là  ?
  • BruBru Membre
    04:54 modifié #4
    dans 1130942431:

    LOL... alors là ...  :o
    Je comprend ce que représente à  présent un NSEvent en tant que conteneur... Mais pour l'envoyer à  un objet... Quel type d'objet d'abord, en fait ? Tout ce que je veux faire, c'est pouvoir simuler un clic de souris à  un endroit précis de l'écran... Que dois-je faire dans ce cas-là  ?


    Laisse ton appli gérer (et dispatcher) ton événement :
    <br />[NSApp sendEvent:tempEvent];<br />
    


    .
  • iShadowiShadow Membre
    04:54 modifié #5
    Alors j'ai donc ajouté le code que tu m'a filé juste après la déclaration du NSEvent. Mais je remarque que cela ne fait rien...
    Par exemple, je m'attends à  ce que une fenêtre autre que celle de l'app se mettre au premier plan... Comme si je cliquait réellement avec ma souris n'importe où sur l'écran, ailleurs que sur la fenêtre déjà  au premier plan. Mais rien ne se passe...
    Alors je pense à  un truc : est ce que cela vient du fait que j'ai spécifié windowNumber à  1 ? Je veux dire que cela clique au coordonnées {100;50} dans le référentiel de cette window ? (j'ai mis un au pif en fait, car je sais pas quoi mettre...)
    (J'espère que je suis assez compréhensible lol ! C'est assez dur à  expliquer  ;))
  • AliGatorAliGator Membre, Modérateur
    04:54 modifié #6
    Il y a 2 effets à  cela :
    - tu envoies l'event à  NSApp, qui est ton application. C'est alors ton application qui va recevoir et gérer l'event. Si l'event est en dehors de l'appli (enfin plus exactement elle va se charger de passer l'event à  ses fenêtres et autres enfants de la responderChain et si personne ne répond parce que y'a personne appartenant à  NSApp sous ton clic) alros l'appli ne fait rien. C'est ensuite l'OS qui gère le clic.

    En fait si je ne me trompe pas l'ordre de réception de l'event lorsque tu cliques c'est OS --> Appli --> Fenêtre, donc forcément si tu envoies ton event à  NSApp, y'a pas de fenêtre sous ton clic simulé, ça fait rien et l'OS n'a pas reçu l'event donc change pas d'appli non plus.

    - Tes coordonnées ne sont peut-être pas dans le bon référenciel, et là  parfois surtout dans ton cas c'est peut-être un peu casse gueule pour trouver lequel utiliser...

    Pourquoi tu n'utiliserais pas un petit coup d'AppleScript ou même plus adapté, un AppleEvent ?
  • 04:54 modifié #7
    Avant de partir dans des trucs tordus, il serait peut être plus utile de dire ce que tu veux faire, car si ça tombe, il y a une solution plus simple.

    Par exemple, si tu veux simplement activer une autre application, NSWorkspace fait ça très bien...
  • iShadowiShadow Membre
    04:54 modifié #8
    En fait, tout ce que je veux faire, c'est simuler le fait de cliquer avec la souris à  un endroit donné de l'écran... Comme si c'est moi qui le fesait... Donc que cela affecte l'interface graphique si jamais je clique sur une autre fenêtre, que ca exécute une action si ca tombe sur un bouton, ...
  • novembre 2005 modifié #9
    Oui oui, ça j'ai compris, mais dans quel but? J'ai vraiment beaucoup de mal à  imaginer dans quels genres de cas on peut avoir besoin de ça, étant donné le manque de contrôle qu'une application peut avoir sur ce qui sort de l'application... En gros tu peux considérer que ça revient à  cliquer au hasard sur ton écran.

    En fait, le seul usage que je vois est un 'dispositif' pour l'accès universel, et il y a des API spécifiques pour cela.
  • iShadowiShadow Membre
    novembre 2005 modifié #10
    En fait c'est un peu dur à  expliquer...
    Je vais essayer de creer un logiciel qui va reconnaitre certains éléments de l'interface puis cliquer dessus... Ce seront des éléments connus par le programme et c'est TRES spécifique à  ce que je veux faire (en gros c'est pas du tout une app que je compte diffuser, à  moins qu'on me le demande lol).
    En gros, je vais connaà®tre la position d'un élément de l'interface, et je veux demander à  ce logiciel de cliquer dessus de multiples fois...
    [EDIT] : voici plus de précisions : je joue à  World of Warcraft, et je voudrais juste qu'un logiciel tourne en tache de fond et vérifie constamment l'état de la jauge de vie, et si il voit qu'elle presque vide, il clique alors sur une potion MDR... Cela m'évite de me faire tuer quand je ne suis pas devant l'ordi...  :brule:
  • 04:54 modifié #11
    Et tu te rends compte de la complexité qu'il y a pour 'trouver' l'élément recherché?

    Si ce que tu dois faire ne concerne qu'un nombre limité d'actions, il est nettement plus simple de passer par AppleScript pour commander l'action directement.
  • iShadowiShadow Membre
    novembre 2005 modifié #12
    Regarde juste un peu plus haut, j'ai modifié mon reply. Pour voir si la jauge est basse, j'ai qu'à  faire un screenshot de la zone ou se trouve la jauge de vie et regarder a quel niveau la couleur verte n'existe plus... Ces éléments d'interface sont fixes.
    [EDIT] : c'est farfelu, je sais  ;)
  • AliGatorAliGator Membre, Modérateur
    04:54 modifié #13
    Comme si c'était aussi simple...
  • novembre 2005 modifié #14
    Sans compter la parano des éditeurs de jeu au sujet de la triche (et à  ce sujet, j'ai lu que le nouveau système de controle de blizzard était pas triste à  ce sujet).

    En tout cas, la réponse à  cette question est hors cocoa.
  • iShadowiShadow Membre
    04:54 modifié #15
    Euh... je considère pas vraiment ça comme de la triche vu que je ne cherche ni à  me faire de l'xp, ni à  hacker les comptes, juste à  me protéger lorsque je suis absent.
    En quoi est-ce hors Cocoa ? Le but de l'application, on s'en fout lol, je voulais juste savoir comment contrôler OS X et simuler un clic de souris... Et c'était tant pour le logiciel, que je ne pense même pas être en mesure de programmer, vu mon niveau actuel ^^, que pour mes connaissances personnelles. En tout cas, je comprend que vous préfériez ne pas m'aider car le but de cette application peut porter à  confusion, et je m'en excuse. Merci quand même de m'avoir donné quelques éléments de réponse, cela me sera utile pour mes futurs programmes ;)
  • 04:54 modifié #16
    Je ne t'accuse pas de tricher, je dis juste que les éditeurs sont paranos à  ce sujet. Quand je vois déjà  les problèmes de faux positifs avec Punkbuster sur un système non suspect, je n'ose pas imaginer ce que ça doit être pour un système qui semble suspect (le système de controle anti-triche de WoW semblant aller très loin dans son contrôle).
    Mais en tout cas, ça peut te donner un avantage dans certains cas, genre si tu oublies de le débrancher dans une bataille ;).

    Quant au but de l'application, comme tu dis, il importe peu. Simplement:
    1. il nous faut des données pour aider efficacement. Les jeux utilisent souvent des bibliothèques spéciales pour la gestion des événements, ce qu'on aurait pu te proposer n'aurait alors servi à  rien. Ce n'est donc pas dans Cocoa que tu trouveras la réponse à  cette question.
    2. Comme tu le dis, tu es encore débutant et sur cette base, tu peux te tromper dans tes choix techniques pour arriver à  un résultat. Le but de ma question était de voir si un autre choix technique n'était pas envisageable, rien de plus.
  • iShadowiShadow Membre
    04:54 modifié #17
    Tu as totalement raison, et c'est vrai que je dois vous donner plus d'infos pour que vous puissiez m'aider, alors excusez moi encore ;)
    Sinon, en fait, je pensait que ce n'était pas la peine de s'intéresser à  tout ce qui touche au jeu en lui-même, puisqu'en fait le programme ne ferait que prendre des screenshots et exécuter une même action à  la souris ; en fait, il pourrait aussi bien tourner sans le jeu ouvert (enfin... il n'y aurait aucun intérêt et ca foutrait le bordel ^^).
    Sinon, si on en revient au sujet, en oubliant totalement ce projet qui n'aurais jamais été abouti vu mes compétences de toute façon, vers quel "environnement" envoyer cet event si on veut qu'il s'exécute sur le système en entier et non pas seulement dans l'app en elle-même ?
  • Eddy58Eddy58 Membre
    novembre 2005 modifié #18
    Comme le dit Renaud, ce n'est pas dans Cocoa qu'il faut chercher, car Cocoa, qui est system-friendly, n'est pas conçu pour faire de telles bidouilles ;). Il faut descendre à  un niveau plus bas. Pour faire un truc pareille, je m'inspirerais de ce qu'il y a ici, et plus particulièrement des fonctions CGPostMouseEvent et CGWarpMouseCursorPosition. :)

    Mais attention au spyware "The Warden", qui surveille tout les processus, pourrait mal considérer ce petit bout de programme, et amener au blocage de ton compte... B)
  • iShadowiShadow Membre
    04:54 modifié #19
    Ok je vais aller voir ces deux fonctions et essayer de les comprendre... En tout cas, vu que je vois que ce genre de bidouille puisse être mal interprètée par "The Warden", alors mieux vaut que je m'abstienne ;)
    Mais c'est toujours intéressant d'en apprendre un peu plus sur le système !
    En tout cas un grand merci pour votre aide :)
  • atshoomatshoom Membre
    04:54 modifié #20
    salut, ishadow (et les autres)
    je voudrais savoir ou en est ton projet parce que étant archidébutant j'ai beaucoup de mal à  élaguer les doc et ton projet de clique m'interresse.
    je me demande aussi comment faire pour simuler l'appuie d'une touche de clavier, un peu comme fait le " visualisateur de clavier"

    avez vous une idée de comment faire ça en C sinon ?
  • Eddy58Eddy58 Membre
    04:54 modifié #21
    Oui, avec la fonction CGPostKeyboardEvent(). :)
  • atshoomatshoom Membre
    04:54 modifié #22
    ok merci, c'est exactement ce que je redoute dans le cocoa, arriver à  trouver une aiguille dans une botte de foin (cette fonction parmi tte la doc).
    en tous cas merci, il ne reste plus qu'à  réussir à  m'en servir pour me faire la main :D
  • Eddy58Eddy58 Membre
    04:54 modifié #23
    Oui, mais là  l'aiguille est dans une autre botte de foin que celle de Cocoa, elle est dans celle de Carbon. ;)

    Dans tout les cas, tu n'as plus qu'à  offrir ta tournée générale, car chercher dans les bottes de foins ça donne soif.  :p :p   :P
  • atshoomatshoom Membre
    04:54 modifié #24
    ok:D je te paie une bierre si jamais on se croise sur appleexpo :D
    je sais pas encore si j'irai ni quel jour j'irai mais je checkerai mes mails de là  bas !
  • atshoomatshoom Membre
    04:54 modifié #25
    pour continuer sur le sujet:
    j'essaie d'utiliser les fonctions CGEventCreateKeyboardEvent (pour simuler l'appui d'une touche) et CGPostEvent (pour poster l'event).
    seulement je patine et je ne comprend pas pourquoi.
    avec le code suivant je suis censé me créer un keyboard event, ça a pas l'air sorcier,
    pourtant à  l'execution quand je click le bouton le programme bloque et le debugger de Xcode s'ouvre car quelque chose ne va pas dans l'instruction (l'appel plutôt)  de
    event1 = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)56, true);
    


    <br />#import &quot;clicker.h&quot;<br /><br />@implementation clicker<br /><br />- (IBAction)clickaction:(id)sender<br />{	<br />	NSLog(@&quot;tracing&#092;n&quot;);<br />	CGEventRef event1, event2, event3, event4;<br />event1 = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)56, true);<br />/*event2 = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)6, true);<br />event3 = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)6, false);<br />event4 = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)56, false);<br />*/	<br /><br />@end<br />
    

    est-ce à  cause d'un appel de fonction carbon depuis une app cocoa ? ou quelque chose dans ce genre là  ?
    Merci, si vous y comprenez quelque chose
  • elfelf Membre
    04:54 modifié #26
    As-tu bien importé le framework CoreFundation (ou le framework qui contiens ces méthodes si ce n'est pas CF)???
  • atshoomatshoom Membre
    04:54 modifié #27
    non, j'ai rien importé, mais ça compile bien et ça plante à  l'exec.
    Je n'y connais pas encore grand chose en cocoa, mais généralement le compilateur refuse de compiler si on a pas inclus le fichier qui défini la fonction, et dans mon cas le compilateur ne dit rien.
    Donc que faut il en penser ?
  • Eddy58Eddy58 Membre
    04:54 modifié #28
    Le plantage est du au fait que le paramètre source doit être correctement défini, pourtant la doc spécifie bien que NULL est une valeur acceptée... ???
    Voici un code fonctionnel : :)
    [tt]
    CGEventSourceRef eventSource=CGEventSourceCreate(kCGEventSourceStatePrivate);

    CGEventRef downEvt=CGEventCreateKeyboardEvent(eventSource,(CGKeyCode)6,true);
    CGEventRef upEvt=CGEventCreateKeyboardEvent(eventSource,(CGKeyCode)6,false);

    CGEventPost(kCGSessionEventTap,downEvt);
    CGEventPost(kCGSessionEventTap,upEvt);

    CFRelease(downEvt);
    CFRelease(upEvt);
    [/tt]
  • atshoomatshoom Membre
    04:54 modifié #29
    excellent :D ça marche :D
    je suis content là ,j'ai appris du concret.

    mais c'est dommage que la doc ne reflète pas la réalité, en effet je pensais que nul était une valeur accepté.
    merci tout plein !
  • Eddy58Eddy58 Membre
    04:54 modifié #30
    Je pense que NULL doit être acceptée, mais dans un certain contexte dont la doc ne fait pas état... :o
Connectez-vous ou Inscrivez-vous pour répondre.