1

J'ai besoin de simuler des appuis de touches dans plusieurs applications lancées en même temps, à partir d'un petit programme tout con. J'utilisais jusqu'ici SendInput, qui fonctionne, mais qui oblige à donner au préalable le focus à l'application ciblée. Du coup dans mon cas j'ai des fenêtres qui vont et viennent, ça clignote, c'est moche (sans compter qu'en plus le PC devient inutilisable puisque l'utilisateur ne doit pas interférer au risque de faire envoyer les touches à une mauvaise application).

Du coup j'aimerais plutôt utiliser SendMessage (ou PostMessage, peu importe) pour lui spécifier le HWND de la fenêtre à laquelle les touches doivent être envoyées.

Mais je ne dois pas avoir compris comment ça fonctionne, puisque même un code tout con comme ça ne produit aucun effet :
HWND hWnd = FindWindow (/* notepad */); /* ici mon hWnd est valide, si je récupère par exemple le titre de la fenêtre, c'est bien notepad */ SendMessage (hWnd, WM_KEYDOWN, VK_RETURN, 0); SendMessage (hWnd, WM_KEYUP, VK_RETURN, 0);
J'aurais pensé que ce truc écrirait un retour à la ligne dans mon notepad ouvert (et dont la boite de texte avait le focus), mais il ne se produit strictement rien, bien que le code de retour de SendMessage soit 0 (donc le message a bien été envoyé).

Est-ce que je suis passé à côté de quelque chose d'évident, genre il faudrait envoyer directement à la textbox et non pas à la fenêtre pour que ça fonctionne (auquel cas cette fonction serait inutilisable), ou bien un problème de droits (je suis sous Windows 7, 64 bits si ça change qqchose), ou bien... ?

Merci pour vos lumières grin
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

2

Heu oui, je pense que tu dois envoyer le message directement au textbox… wink
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

3

iwannabeamaki (./1) :
Du coup j'aimerais plutôt utiliser SendMessage (ou PostMessage, peu importe)

Houla non, y'a une putain de différence entre les deux, j'y ai été confronté avec ActiveSync et la reconnexion d'un PocketPC sous une appli !

Kochise
avatar
Si Dieu m'a de nouveau fait homme, cette fois il m'a pas raté : marcher sur l'eau et dupliquer les pains, ça marche p'us :/

4

GoldenCrystal (./2) :
Heu oui, je pense que tu dois envoyer le message directement au textbox… wink

Y'a pas moyen de déclencher une propagation automatique ? (je pensais que ça allait être le cas sans que je m'en soucie). Parceque le descriptif de la fonction SendMessage indique qu'elle est prévue pour envoyer son message "to a window"... s'il faut lui donner le handle d'un composant, déjà la fonction perd tout son intérêt (impossible d'envoyer des touches à une fenêtre arbitraire), mais surtout j'ai l'impression que ça ne correspond plus à la doc :/
Kochise (./3) :
Houla non, y'a une putain de différence entre les deux, j'y ai été confronté avec ActiveSync et la reconnexion d'un PocketPC sous une appli !

Autre chose que le fait que l'une soit synchrone et l'autre asynchrone ? Parceque si c'est juste ça, dans mon cas ça ne change pas grand chose (tant qu'à faire si c'est synchrone c'est mieux, mais c'est vraiment le cadet de mes soucis)
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

5

'Window' est à comprendre au sens large dans ce cas, c'est en fait tout contrôle qui a son propre HWND (donc ça peut être une fenêtre, un bouton, une zone de texte, etc.)
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

6

Bon bah si c'est ça et qu'il n'y a pas moyen de propager automatiquement l'évènement, tant pis, je repars sur SendInput :/

Merci pour les précisions.
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

7

Je pense qu'il doit y avoir moyen de bidouiller pour obtenir ce que tu cherches à faire, mais faut que je regarde la doc plus en détail.
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

8

bin faut trouver le hwnd du controle, a part ça tu feras pas grand chose grin

la boucle d'évènements de la fenêtre ne sait pas forcément dispatcher les messages à ses enfants smile

9

Oui, l'idée serait de trouver quel est le contrôle qui a le focus dans la fenêtre, et lui envoyer directement les messages.
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

10

Un truc me vient à l'esprit : imaginons que je fasse une appli qui n'utilise pas les contrôles habituels de Windows, à la place je recode tout mon système de composants, par exemple en OpenGL.

Quand je tape un truc au clavier, Windows ne peut donc transmettre l'évènement qu'à la fenêtre et laisser l'appli dispatcher, puisque les notions de focus et autres lui sont inconnues.

Il doit donc bien y avoir moyen de simuler cet évènement clavier au niveau de la fenêtre sans avoir à s'intéresser au niveau composant, non ? (d'ailleurs SendInput marche très bien dans ce cas, son seul soucis c'est qu'il ne permet que d'envoyer à la fenêtre qui a le focus au lieu de permettre de spécifier un handle).
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

11

Si tu crées une fenêtre qui ne contient aucun contrôle Windows, le focus ne peut être attribué qu'à la fenêtre elle-même. Dans ce cas là, c'est simple : c'est la fenêtre qui reçoit tous les messages, et ta solution du dessus fonctionne. Mais s'il y a des contrôles dans la fenêtre, c'est à celui qui a le focus que tu dois envoyer les messages.
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

12

voila.

et le problème fondamental c'est que les controles windows sont des fenêtres dotées de leur propre callback de gestion des messages.

13

Oki, donc une solution pourrait être de rechercher le hWnd qui a le focus (j'ai pas encore cherché si c'était possible), de lui envoyer le message, ou de l'envoyer à la fenêtre si aucun hWnd n'a pu être trouvé.

Ça reste peut-être faisable, à vérifier ^^
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

14

Le problème c'est que le contrôle qui a le focus est unique et fait toujours partie de la fenêtre active… (Puis apparemment GetFocus ne fonctionne que pour les fenêtres du thread qui l'appelle, à moins que tu ne l'aie au préalable rattaché à un autre thread… Mais je n'ai jamais utilisé ça et la doc ne précise pas si ça fonctionne entre deux threads dans des processus différents.)
J'avais regardé tout à l'heure si y'avait un moyen d'obtenir le contrôle qui "aurait" le focus dans une fenêtre précise, mais comme je le pensais ça n'a pas l'air d'être possible… (=> Vérifier une seconde fois ne coute rien, j'ai pas non plus cherché 3h)
En tout cas si tu dois activer les fenêtres toi même tu ne vas rien gagner par rapport à SendInput ^^

Enfin sinon, selon la nature exacte des opérations que tu désires effectuer, tu peux probablement faire plus de choses avec une bonne vielle injection de DLL, mais ce n'est pas forcément une option que tu peux choisir… ^^
(Les injection de DLL peuvent être bloquées par les politiques de sécurité du système, incluant éventuellement une demande directe du processus ciblé… Et puis à la base c'est un peu un gros hack, mais ça… grin)
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

15

Ben j'imagine que SendInput() aussi peut être bloqué (sinon ça serait une énorme faille de sécurité grin)
avatar
Zeroblog

« Tout homme porte sur l'épaule gauche un singe et, sur l'épaule droite, un perroquet. » — Jean Cocteau
« Moi je cherche plus de logique non plus. C'est surement pour cela que j'apprécie les Ataris, ils sont aussi logiques que moi ! » — GT Turbo

16

iwannabeamaki (./13) :
Oki, donc une solution pourrait être de rechercher le hWnd qui a le focus (j'ai pas encore cherché si c'était possible), de lui envoyer le message, ou de l'envoyer à la fenêtre si aucun hWnd n'a pu être trouvé.

Ça reste peut-être faisable, à vérifier ^^

oui et non, y'a un truc spécifique (à l'arrache je trouve SendDlgItemMessage mais il me semble qu'il en existe un autre d'un autre nom) pour envoyer un message à un contrôle en particulier....
avatar
Webmaster du site Ti-FRv3 (et aussi de DevLynx)
Si moins de monde enculait le système, alors celui ci aurait plus de mal à nous sortir de si grosses merdes !
"L'erreur humaine est humaine"©Nil (2006) // topics/6238-moved-jamais-jaurais-pense-faire-ca

17

Rah, je pensais avoir trouvé une solution avec la fonction GetGUIThreadInfo, puisqu'elle retourne une structure qui indique entre autre le HWND du composant qui a le focus, donc exactement ce dont j'ai besoin.

Malheureusement cette info ne semble être disponible que si la fenêtre qui contient le composant a elle-même le focus. Je ne comprends pas cette restriction... quand on donne manuellement le focus à un composant C d'une fenêtre A (on clique dans une textbox par exemple), puis qu'on sélectionne une autre fenêtre et qu'on revient à la fenêtre A, c'est toujours le composant C qui a le focus, donc cette info n'a pas été perdue entre temps. Je ne vois pas trop pourquoi GetGUIThreadInfo ne permet pas de l'obtenir :/
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

18

Le problème, c'est qu'il y a des trucs que tu ne peux tout simplement pas faire avec SendMessage(WM_KEYDOWN): Des combinaisons de touches. Impossible de simuler SHIFT+A pour avoir un A majuscule, j'ai essayé: Pour ça, seule la fonction SendInput() marche. Et encore, sans doute pas pour des fenêtres avec un niveau d'intégrité "supérieur" (UAC).
avatar
Maintenant j'ai la flemme de garder une signature à jour sur ce site. Je n'ai même plus ma chaîne Exec sous la main.

19

comment fait Synergy? c'est open source d'ailleurs.

20

Bah, suffit de pas s'y prendre comme un manche…
La gestion de l'entrée clavier/souris sous Windows est certes un peu bordélique… (Disons que c'est un mélange de trucs bien pensés avec d'autres trucs complètement débiles) Mais on peut s'en démerder la plupart du temps.
Les applications ne peuvent recevoir les entrées clavier que de deux manières: par les messages, ou avec des fonctions comme GetKeyState(). Et les implémentations par défaut n'utilisent pas la deuxième possibilité (Ou alors peut-être parfois en complément de l'autre) donc…

(PS: Shift + A c'est [Shift Down, A Down, A Up, Shift Up] ou [Shift Down, A Down, Shift Up, A Up]… Ou aussi juste 'A'. Ça fait plusieurs trucs à essayer tongue)
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

21

^J'ai déjà essayé ces deux suites avec SendMessage(WM_KEYDOWN), et ça ne marchait pas. Puis j'ai eu confirmation que ça n'était pas censé marcher.
avatar
Maintenant j'ai la flemme de garder une signature à jour sur ce site. Je n'ai même plus ma chaîne Exec sous la main.

22

Évidemment, car ça ne peut fonctionner qu'avec PostMessage -_-
Avec SendMessage tu dois aussi envoyer toi même les WM_CHAR.

Le post que tu link explique juste qu'à cause des spécificités des systèmes d'entrées telles que les IME, tu risques facilement de faire un code qui ne va pas fonctionner comme tu veux sur tous les systèmes (en gros c'est une garantie à 100% tongue), pas que ça ne marchera jamais.
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

23

Il explique aussi que SHIFT ne marche pas, et c'est avec PostMessage() que j'avais essayé de toute façon. Notepad ne voulait rien savoir.
avatar
Maintenant j'ai la flemme de garder une signature à jour sur ce site. Je n'ai même plus ma chaîne Exec sous la main.

24

Il explique pas que Shift ne fonctionne pas, il explique (comme je l'ai sous entendu plus haut) que si l'application utilise GetKeyState à la place de lire le contenu des messages, bah tes messages sont sans effet. tongue
Mais j'ai jamais eu l'impression que les contrôles par défaut de Windows utilisaient GetKeyState…
Par contre, Notepad est probablement un mauvais exemple, car la zone de texte est tout sauf un textbox standard (de mémoire; ça a peut-être été corrigé mais j'en doute fortement ^^).
(D'ailleurs à une époque si tu faisais un middle click dans la zone de texte de notepad tu avais l'icône de l'autoscroll qui clignotait brièvement, après test il a l'air de fonctionner à 100% maintenant… Je ne sais pas si c'est Windows 7 ou le driver de ma souris qui a provoqué ce changement)
Enfin, je ferai des tests quand j'aurai le temps, mais normalement tu as bien moyen de berner les applications honnêtes. (Celles qui respectent les procédures standard de traitement des messages)

Sinon, le meilleur moyen est l'injection de dll. (bis ^^)
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

25

Je suis surpris par ce que tu dis de Notpad. J'essaierai peut-être de me faire un programme avec une textbox standard pour comparer...
avatar
Maintenant j'ai la flemme de garder une signature à jour sur ce site. Je n'ai même plus ma chaîne Exec sous la main.

26

Hmm en fait, je suis presque certain d'avoir lu un article, il y a longtemps, expliquant que notepad contenait un contrôle dérivé du code du textbox de windows (donc d'une ancienne version de celui-ci, genre celui de Windows 3.1), mais je n'arrive pas à remettre la main dessus T_T
(J'étais aussi quasi certain que c'était sur The Old New Thing, mais en ayant regardé vite fait les résultats ça n'a pas l'air d'être dedans sad )
avatar
Le scénario de notre univers a été rédigée par un bataillon de singes savants. Tout s'explique enfin.
T'as un problème ? Tu veux un bonbon ?
[CrystalMPQ] C# MPQ Library/Tools - [CrystalBoy] C# GB Emulator - [Monoxide] C# OSX library - M68k Opcodes

27

GoldenCrystal (./24) :
Sinon, le meilleur moyen est l'injection de dll. (bis ^^)

C'est sûr que c'est beaucoup plus fiable, mais mon objectif était de rester générique donc l'injection de DLL n'est pas possible :/

Sinon je comprends pas trop le lien de Link, mais ça sous-entend que le lParam passé au PostMessage (qui peut contenir des flags indiquant l'état des touches shift, ctrl et alt) n'est pas fiable ? Parceque si c'est ça, je comptais juste faire comme ce que décrit GC en ./20 : keydown+shift, keydown+a, keyup+a, keyup+shift (donc 4 PostMessage en tout). En revanche pour une raison qui m'échappe SendMessage ne fonctionne pas du tout.

Pour résumer, j'ai encore des bugs avec PostMessage mais ça permettrait *presque* de faire ce que je veux si je pouvais chopper le handle du contrôle qui a le focus. Manque de bol, je n'ai aucun moyen de chopper ce handle si la fenêtre qui contient le contrôle n'est pas au premier plan.

Faute de solution, il faudra que je reparte sur SendInput avec des SetForegroundWindow qui clignottent de partout sad
avatar
All right. Keep doing whatever it is you think you're doing.
------------------------------------------
Besoin d'aide sur le site ? Essayez par ici :)

28

Je me rends compte que synergy n'a pas le souci que tu rencontres, vu qu'ils n'envoient les touches et les clics de souris qu'à la fenêtre active sorry

29

Tu es sûr qu'il n'y a pas au moins certains programmes dans le lot qui supportent OLE Automation?
avatar
Maintenant j'ai la flemme de garder une signature à jour sur ce site. Je n'ai même plus ma chaîne Exec sous la main.

30

Qqun peut me dire ce qu'est une injection de dll svp ? Intercepter tous les appels d'une dll pour faire exécuter une fonction qu'on veut modifier ?