Sendmessage sans effet

Sendmessage sans effet - C++ - Programmation

Marsh Posté le 18-06-2015 à 20:05:34    

Bonjour à tous!  :hello:  
Après des heures de recherches je décide enfin de poser ma question sur un forum:
Comment envoyer un message (entrée clavier/souris) à une fenêtre en particulier?
J'ai déjà essayé:
Postmessage: réussite pour certaines fenêtres (zones de texte) mais pas celles qui m'interressent
Keybd_event: idem
SendMessage: échec sur toutes les fenêtres testées (et retourne 0 à chaque fois)
J'ai lu quelque part que l'on peut combiner keybd_event et sendmessage mais sendmessage n'a apparemment aucun effet
Pourtant le handle est bien récupéré et il n'y a pas l'air d'y avoir de problème de communication avec la fenêtre puisque setforegroundwindow marche...
J'ai vu que si la fenêtre est une fenêtre fille, le message n'est transmit qu'à la fenêtre mère et ne parviendrait donc pas à la fenêtre fille (mais alors pourquoi setforegroundwindow marche?)
Je ne m'y connais pas beaucoup donc la je suis un peu perdu :pt1cable:  
C'est dans le but de créer des bots qui pourraient interagir automatiquement avec certaines applications (comme un humain) , et même pendant que j'utilise le pc. J'ai cru comprendre qu'il pouvait y avoir des sortes "d'interférences" entre les vraies entrées et les entrée simulées, même envoyées directement à l'application....
Merci de me corriger si j'ai dit des choses absurdes et de me permettre de mieux comprendre tout ça!  :)  
Bonne journée à tous!

Reply

Marsh Posté le 18-06-2015 à 20:05:34   

Reply

Marsh Posté le 18-06-2015 à 21:27:13    

Nicolas_555 a écrit :

Bonjour à tous!  :hello:  
Après des heures de recherches je décide enfin de poser ma question sur un forum:
Comment envoyer un message (entrée clavier/souris) à une fenêtre en particulier?
J'ai déjà essayé:
Postmessage: réussite pour certaines fenêtres (zones de texte) mais pas celles qui m'interressent
Keybd_event: idem
SendMessage: échec sur toutes les fenêtres testées (et retourne 0 à chaque fois)
J'ai lu quelque part que l'on peut combiner keybd_event et sendmessage mais sendmessage n'a apparemment aucun effet
Pourtant le handle est bien récupéré et il n'y a pas l'air d'y avoir de problème de communication avec la fenêtre puisque setforegroundwindow marche...
J'ai vu que si la fenêtre est une fenêtre fille, le message n'est transmit qu'à la fenêtre mère et ne parviendrait donc pas à la fenêtre fille (mais alors pourquoi setforegroundwindow marche?)
Je ne m'y connais pas beaucoup donc la je suis un peu perdu :pt1cable:  
C'est dans le but de créer des bots qui pourraient interagir automatiquement avec certaines applications (comme un humain) , et même pendant que j'utilise le pc. J'ai cru comprendre qu'il pouvait y avoir des sortes "d'interférences" entre les vraies entrées et les entrée simulées, même envoyées directement à l'application....
Merci de me corriger si j'ai dit des choses absurdes et de me permettre de mieux comprendre tout ça!  :)  
Bonne journée à tous!


 
Pourquoi réinventer la roue ? Il existe plein de solutions genre xdotool sous Linux ou encore https://www.autoitscript.com/site/autoit/ sous windows... (Il y en a d'autres)

Reply

Marsh Posté le 18-06-2015 à 23:00:27    

Merci! Je ne connaissais pas ce genre de logiciels. Cependant, ça m'intéresserait de comprendre pourquoi mon code ne fonctionnait pas, quelqu'un saurait-il me l'expliquer? :D

Reply

Marsh Posté le 18-06-2015 à 23:53:58    

Tu utilise quelle librairies ?
J'ai déjà pondu un truc qui permet de contrôler la souris avec une manette, en passant direct par l'API Windows j'avais pas eu de soucis..


---------------
Perhaps you don't deserve to breathe
Reply

Marsh Posté le 19-06-2015 à 00:05:49    

Je veux bien voir le code de Nicolas_555

Reply

Marsh Posté le 19-06-2015 à 10:40:16    

J'ai commencé par essayer d'envoyer une lettre, donc:
 
#include <stdio.h>
#include <windows.h>
int main(int argc, char * argv[])
{
Sleep(3000);
HWND handle = GetForegroundWindow();
SetForegroundWindow(handle);   //inutile je suppose mais c'était pour tester la fonction (et elle marche)
SendMessage(handle, 'A', 0, 0);
}
En remplaçant SendMessage par keybd_event('A', 0, 0, 0); ou PostMessage(handle, 'A', 0, 0); le code marche pour certaines fenêtres, pas d'autres...
J'ai remarqué aussi que keybd_event('A', 0, KEYEVENTF_KEYUP, 0); donne le même résultat que keybd_event('A', 0, 0, 0); mais je crois avoir compris que c'est normal dans certains cas.
Je me demande s'il ne faut pas aussi ajouter un paramètre correspondant à la zone de texte, mais je n'y connais rien :sarcastic:  
J'ai essayer des messages autres que du texte, donc:
SendMessage(handle, VK_F2, 0, 0);
par exemple mais sans résultat (pourtant je suppose qu'ici il n'y a pas d'autres paramètre à donner, enfin je suppose)


Message édité par Nicolas_555 le 19-06-2015 à 10:45:29
Reply

Marsh Posté le 19-06-2015 à 11:11:20    

Ben déjà, tu peux peut être tester le retour de ta fonction:
if (handle) {
  SendMessage(handle, 'A', 0, 0);  
}
else {
  ... // un printf, message box ou autre moyen de t'informer que GetForegroundWindow t'a renvoyé null.
}
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 19-06-2015 à 11:59:22    

J'ai une ligne en plus pour afficher le handle de la fenêtre donc je suppose que si il m'affiche qqch c'est que la fonction marche. Et la fonction SetForegroudWindow met la bonne fenêtre au premier plan.
J'ai quand même rajouté le test. Le handle est bien récupéré. (Mais toujours rien)

Reply

Marsh Posté le 19-06-2015 à 14:45:18    

Ben je comprends pas ce que tu fais en fait:
Tu envoies le message 'A' qui va être casté en UINT avec la valeur 65, soit le message système WM_COMPACTING (qui ne marche qu'avec les applis 16 bits, pour demander de libérer de la mémoire, si possible).
Donc je ne vois pas trop ce que tu attends comme réaction des fenêtres qui vont recevoir ce message.
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 19-06-2015 à 14:51:37    

SendMessage(handle, 'A', 0, 0); n'est pas équivalent à l'appui de la touche A par l'utilisateur?

Reply

Marsh Posté le 19-06-2015 à 14:51:37   

Reply

Marsh Posté le 19-06-2015 à 15:05:26    

:pt1cable: Collector, ta question!
Faudrait un minimum apprendre la programmation Windows avant de se lancer dedans et lire la doc (parce que SendMessage est une des fonctions les plus basiques de l'API, et elle fait ce qu'elle dit: elle envoie des messages (et y'en a des centaines possibles)).
Dans ton cas, ça doit être quelque chose comme SendMessage(handle, WM_CHAR, 'A', 1);
 
A+,
 


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 19-06-2015 à 15:24:57    

Merci je ne savais pas qu'il fallait mettre WM_char (le type de message qu'on envoi je suppose).
Ça marche pour la zone de texte de vs mais pas sur le bloc note, skype etc...
Et VK_F1 m'écrit un p, donc je suppose qu'il ne faut pas utiliser WM_char pour ça, mais je n'ai aucune idée de ce qu'il faut....


Message édité par Nicolas_555 le 19-06-2015 à 15:27:08
Reply

Marsh Posté le 19-06-2015 à 15:57:18    

Ben oui, si tu veux émuler l'envoi de touches claviers, c'est tout a fait autre chose que l'envoi de d'un message caractère.
 
Il faut proceder ainsi pour simuler l'envoi de la touche F1:
// HWND before = GetFocus();
SetFocus(handle);  // On met le focus clavier sur la fenêtre ou l'on envoie les touches
keybd_event( VK_F1, 0, 0, 0 ); // simulation de l'appui de la touche
keybd_event( VK_F1, 0, KEYEVENTF_KEYUP, 0 ); // simulation du relachement de la touche
// SetFocus(before);  
 
Si tu veux un exemple plus parlant, pour envoyer des chaines, en Delphi et facilement adaptable, cf la fin de ce fil: http://www.developpez.net/forums/d [...] e-wm_char/
Ou le code de ce programme: http://www.codeproject.com/Articles/6819/SendKeys-in-C
 
A+,


Message édité par gilou le 19-06-2015 à 15:58:38

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 19-06-2015 à 16:37:53    

Tu te feras nettement moins chier avec AutoIt :o Tu peux repérer une fenêtre et récupérer son handle avec tout ou partie du libellé qui apparaît dans son titre, voire même, dans le cas où 2 fenêtres auraient le même titre, filtrer en fonction d'une portion de texte qui apparaît dans la fenêtre.
 
Ensuite, t'as tout un tas de fonctions pour piloter direct les contrôles d'une fenêtre (fortement inspiré de l'API Windows au passage), pour attendre qu'une fenêtre s'ouvre, devienne active (avec un timeout ou sans)...
 
Et pour l'envoi de caractères ou de raccourcis clavier, y'a Send().
 
Y'a aussi des fonctions pour faire des captures d'écran, enregistrer en jpg, bmp, png des images, les ouvrir et les manipuler.
 
Bref, t'as vraiment tout pour t'éclater et automatiser n'importe quelle appli. Après, AutoIt marche beaucoup moins bien pour manipuler des applis codées en Labview : impossible de récupérer les contrôles (que le handle de la fenêtre principale de l'appli). Mais avec un peu d'astuce et de traitement d'image, on s'en sort. ;)


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 19-06-2015 à 18:43:46    

Merci beaucoup, mais les fonction getfocus et setfocus retournent systématiquement NULL, donc le keybd_event n'agit pas que sur le fenêtre voulue. Quelle peut-etre la cause? Je n'ai pas l'impression que le problème vienne du handle de la fenêtre, donc je suis encore perdu :(

Reply

Marsh Posté le 20-06-2015 à 02:32:27    

Si SetFocus te retourne NULL, faut aller en chercher la cause avec GetLastError.
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 20-06-2015 à 15:44:27    

Après vérification avec GetLastError():
Pas de problème avec getfocus: GetLastError()=0
Après l'appel de SetFocus(handle), GetLastError()=5, ce qui correspond à access denied.
Si GetFocus() retourne NULL, SetFocus devrait retourner NULL sans causer d'erreur je suppose, mais en appelant GetFocus() après SetFocus(), le focus vaut toujours NULL.
(Mais si je clique sur une zone de texte (manuellement), le focus clavier ne devrait-il pas avoir une valeur différente de NULL?)
Donc le programme n'a pas les droits de modifier le focus mais peut obtenir le focus actuel (getfocus ne génère pas d'erreur), i.e droits en lecture mais pas en écriture si j'ai bien compris.  Comment corriger ce problème?   :)


Message édité par Nicolas_555 le 20-06-2015 à 15:52:31
Reply

Marsh Posté le 20-06-2015 à 17:46:59    

Ben tu fais comme moi, tu cherches sur le web, et tu finis par trouver les infos. Du temps ou je faisais de la programmation windows, ce que je t'ai indiqué marchait, mais il semble que ça ait changé depuis, et que ça soit devenu plus complexe.
 
Il faudrait faire au vu de ce que j'ai lu:
1) chopper le thread id de la fenêtre cible.
DWORD dwTargetThread = GetWindowThreadProcessId(handle, NULL);
2) Détacher les mécanismes d'input du programme et les attacher a la fenêtre cible  
AttachThreadInput(GetCurrentThreadId(), dwTargetThread, TRUE);
3) Appeler alors SetFocus (ca marchait pas à cause de l'omission de l'étape 2)
SetFocus(handle);
4) Appeler SetForegroundWindow
SetForegroundWindow(handle);
 
et on doit pouvoir envoyer les caractères a ce stade
keybd_event( VK_F1, 0, 0, 0 ); // simulation de l'appui de la touche
keybd_event( VK_F1, 0, KEYEVENTF_KEYUP, 0 );
 
Note: L'étape 4 est normalement inutile si tu as fait  
HWND handle = GetForegroundWindow();  
pour obtenir le handle (c'est utile s'il est obtenu autrement).
Je pense aussi que le SetFocus est sans doute inutile aussi mais c'est à tester.
(Ça peut être utile si c'est un item d'une boite de dialogue qui a le focus et que tu veux envoyer tes caractères plus haut dans la hiérarchie des fenêtres en mettant le focus sur un parent...)
 
 
Et il faut sans doute faire  
AttachThreadInput(GetCurrentThreadId(), dwTargetThread, FALSE);  
une fois qu'on a fini, pour détacher les mécanismes d'input de fenêtre cible
 
A+,


Message édité par gilou le 20-06-2015 à 21:28:21

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 22-06-2015 à 10:36:52    

Où se faire moins chier et utiliser AutoIt qui permet de faire tout ça très simplement ;)


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 22-06-2015 à 19:11:26    

Et s'il a envie d'apprendre par lui même à programmer ce genre de choses? :p
 
A+,


---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --
Reply

Marsh Posté le 22-06-2015 à 23:03:34    

Ben il peut le faire... avec AutoIt :D Y'a toujours la notion de handle c'est juste que t'as pas besoin de réinventer les couches de bas niveau. C'est un peu comme quand tu fait du traitement d'image : se faire chier à recoder les fonctions d'ouverture de fichier jpg, bmp, png, c'est chiant. C'est plus sympa d'avoir des fonctions de plus haut niveau, te permettant de te concentrer sur le code plus intéressant pour modifier une image ;)


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 30-06-2015 à 19:12:54    

--@rufo
Quel est le probleme a vouloir pousser un peu un language plutot que chercher la facilité.  
J'aimerais faire la meme chose que lui (ET EN C++!), et je ne souhaite pas utiliser AutoIt. Et c'est mon droit :)!
Tes messages sont gênant (Car instant, et répetant toujours la même chose)..
 
Pour ma part, je pense être un peu plus débutant que l'OP x)!
Du coup, je comprend pas du tout son morceau de code.
Je regarderais ca a tête reposé demain. :)!  
(Mon 'bot' fonctionne si on laisse la fenetre au premier plan ;P)
 
Edit:  
Ayant donc regarder, je n'y comprends vraiment rien x)!
Je pense que je reviendrais chercher comprendre quand j'aurais progresser xP!
(Un peu de mal a me servir des classes/header, encore, dans l'architecture, je veux dire, avec les #include)
 
personnellement, un #include <SendKeys.h> ne fonctionne pas.


Message édité par feliwyn le 01-07-2015 à 14:39:00
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed