PostMessage [Résolu]

la_gavorade
Messages postés
24
Date d'inscription
jeudi 22 juillet 2004
Dernière intervention
30 juin 2006
- 27 juin 2006 à 14:52 - Dernière réponse : cs_mounjetado
Messages postés
69
Date d'inscription
lundi 13 mars 2006
Dernière intervention
4 août 2008
- 3 juil. 2006 à 11:09
Bonjour à tous,

J'ai un soucis avec PostMessage (ça va être un peu long, je vous préviens) :
Voilà, j'ai fait une appli qui entre autres lance un programme externe (programme de stats dont l'interface ressemble bcp à une invite de commande), et j'ai besoin de simuler des entrées clavier pour lancer les macros de ce programme externe.
Alors quand je le lance sur mon poste, pas de pb, je fais des keybd_event et ça marche. Le pb est que je veux également qu'elle fonctionne à partir d'un serveur virtuel auquel j'accède par une connexion bureau à distance. Là encore, si je reste sur le bureau du serveur virtuel, ça marche, mais dès que je ferme ou minimise la fenêtre de ce serveur, alors le keybd_event ne marche plus.
J'ai bien essayé de forcer la mise au premier plan de la fenêtre du prg en utilisant SetForeGround, et c'est OK....là encore si je reste sur le bureau du serveur, sinon ça marche pas.

Ma piste d'aujourd'hui, c'est d'utiliser un PostMessage en indiquant le handle de la fenêtre du prg, puis les touches à simuler, mais là bizarre, mon PostMessage ne fait rien du tout.
(J'ai bientôt fini). J'ai donc créé un petit test qui met une fenêtre Notepad en premier plan puis écrit dedans, et ça marche pas. Je vous montre le code correspondant :
J'utilise un FindWindow(Notepad) pour trouver le handle du Notepad, puis un SetForeGround(handle_notepad). Tout ça, ça marche
C'est maintenant que ça marche plus, et pourtant la fenêtre Notepad est bien en surbrillance :

PostMessage(handle_notepad, WM_KEYDOWN, VK_DECIMAL, 0) ;
PostMessage(handle_notepad, WM_KEYUP, VK_DECIMAL, 0) ;

// Là, il ne se passe rien, et pourtant le programme va bien au delà de ces deux lignes de code, il n'est pas bloqué... J'y comprends pas grand chose...

Merci de votre aide !
Afficher la suite 

Votre réponse

17 réponses

Meilleure réponse
Cirec
Messages postés
4229
Date d'inscription
vendredi 23 juillet 2004
Dernière intervention
3 août 2018
- 28 juin 2006 à 18:55
3
Merci
Salut,

en ce qui concerne WM_KEYDOWN et WM_KEYUP ils ne fonctionnent pas
pourquoi ? ... je ne sais pas

mais en revenche l'exemple suivant fonctionne mais je ne sais pas  s'il te sera util :

var
  Form1: TForm1;
  handle_notepad, Handle_Edit : THandle;



implementation




{$R *.DFM}




procedure TForm1.Button1Click(Sender: TObject);
begin
handle_notepad := findwindow('notepad', nil) ; //jusque là, OK
SetforegroundWindow(handle_notepad) ; // Encore OK, la fenêtre Notepad est active
Handle_Edit := FindWindowEx(Handle_NotePad,0, 'Edit',Nil);// il faut chercher le Handle de l'Edit
SendMessage(Handle_Edit, WM_CHAR, ord('.'), 0) ; //   VK_DECIMAL
end;

@+
Cirec

Merci Cirec 3

Avec quelques mots c'est encore mieux Ajouter un commentaire

Codes Sources a aidé 94 internautes ce mois-ci

Commenter la réponse de Cirec
Utilisateur anonyme - 27 juin 2006 à 16:03
0
Merci
Salut,

D'apres ce que je comprends des que tu quittes la pièce ton appli fonctionne plus ? et si tu utilisais un épouvantail ?? Peut etre que ca fonctionnerait.

L'autre solution est de faire appel à un exorsiste. Je crois que fOxi a une incatation spéciale ou il faut se mettre tout nu et danser la coucaratcha avec un balai à la main. Mais ca fonction qu'à la pleine lune.

Plus sérieusement, pourrais tu reformuler ta question de facon plus claire car la il est assez difficile de comprendre (trop d'informations pas tres clairs)

Merci à toi

A+ ;)
Commenter la réponse de Utilisateur anonyme
la_gavorade
Messages postés
24
Date d'inscription
jeudi 22 juillet 2004
Dernière intervention
30 juin 2006
- 27 juin 2006 à 16:32
0
Merci
Alors pour Francky, dont l'humour n'a rien à envier à celui de Guy Montagné pour ne citer que lui, je donne une définition du terme "bureau", qu'on peut trouver facilement sur internet :

"Ecran qui s'affiche après le démarrage de l'ordinateur. Y apparaissent différentes icônes : Poste de travail, corbeille, etc..."

De la même façon, cliquer sur une souris ne signifie pas pour autant qu'on fait du mal à un petit rongeur...

Quand je quitte "le bureau du serveur virtuel", en termes plus clairs, je clique sur la petite croix en haut à gauche de la fenêtre dans laquelle s'affiche le bureau du serveur virtuel. Pas besoin d'exorciste (avec un "c") pour tout ça...

Bref, désolé d'avoir été un peu obscur, je ré-explique mon pb en vous donnant le code du test :
handle_notepad := findwindow('notepad', nil) ; //jusque là, OK
Setforeground(handle_notepad) ; // Encore OK, la fenêtre Notepad est active
PostMessage(handle_notepad, WM_KEYDOWN, VK_DECIMAL, 0) ;
PostMessage(handle_notepad, WM_KEYUP, VK_DECIMAL, 0) ; //Pas OK, le point (ou la virgule, bref le symbole décimal) ne s'affiche pas dans ma fenêtre.

Je reprécise qu'en utilisant keybd_event ça marche mais ça ne résoud pas mon pb (je vais pas répéter mon histoire de bureau virtuel à minimiser et de connexion à distance...mais faudrait que je puisse utiliser soit PostMessage, soit SendMessage). Alors, y'a quoi qui coince avec mon PostMessage ???

Merci d'avance !
Commenter la réponse de la_gavorade
Matt 261
Messages postés
1201
Date d'inscription
mercredi 2 novembre 2005
Dernière intervention
10 septembre 2011
- 27 juin 2006 à 19:09
0
Merci
Je la trouve très bien moi la réponse de Francky.



@+
 Matt

La paresse est la mère du génie...
Commenter la réponse de Matt 261
la_gavorade
Messages postés
24
Date d'inscription
jeudi 22 juillet 2004
Dernière intervention
30 juin 2006
- 28 juin 2006 à 11:51
0
Merci
Bon, Matt et Francky, j'ai vu sur DelphiLab que vous étiez copains comme cochons, pas étonnant donc qu'une solidarité amicale se dégage pour me renvoyer dans mes 22...
Désolé d'avoir été un peu agressif, si vous l'avez ressenti comme ça, mais l'énervement dû au bug que je rencontre depuis deux jours et qui bloque le travail d'une équipe de 8 personnes qui attendent sa résolution additionné à la désagréable impression d'être pris pour un gros blaireau (plus le stress d'un 1/8 de finale à venir le soir même) m'ont fait perdre ma retenue habituelle. Encore désolé.

Est-ce que l'absence de réponses depuis est due à un boycott-punition, au fait que ma demande n'est toujours pas claire, ou au fait que personne ne trouve la solution ?

Merci d'avance.

Thomas.
Commenter la réponse de la_gavorade
Matt 261
Messages postés
1201
Date d'inscription
mercredi 2 novembre 2005
Dernière intervention
10 septembre 2011
- 28 juin 2006 à 12:01
0
Merci
Disons que tout est un peu confondu dans ce que essaye de nous expliquer. Mais nous sommes là pour t'aider donc si tu peux réexpliquer plus clairement, nous ferons notre possible pour t'aider.

@+
 Matt

La paresse est la mère du génie...
Commenter la réponse de Matt 261
la_gavorade
Messages postés
24
Date d'inscription
jeudi 22 juillet 2004
Dernière intervention
30 juin 2006
- 28 juin 2006 à 14:05
0
Merci
Ok, on oublie (pour le moment) les pb de connexion à distance, etc etc et on se concentre sur mon petit test qui marche pas et qui me déconcerte.
J'ai créé un tout petit prog pour tester l'utilisation de PostMessage ou SendMessage, qui contient juste un bouton avec les lignes de codes ci-dessous lorsqu'il est activé (j'ai une fenêtre Notepad ouverte au préalable):

handle_notepad := findwindow('notepad', nil) ; //jusque là, OK, je trouve le handle de ma fenêtre Notepad.
Setforeground(handle_notepad) ; // Encore OK, la fenêtre Notepad est activée et mise au premier plan.
PostMessage(handle_notepad, WM_KEYDOWN, VK_DECIMAL, 0) ;
PostMessage(handle_notepad, WM_KEYUP, VK_DECIMAL, 0) ; //Pas OK, le point (ou la virgule, bref le symbole décimal) ne s'affiche pas dans ma fenêtre.

Je veux juste savoir pourquoi j'arrive pas à afficher mon symbole décimal dans cette fenêtre Notepad grâce à PostMessage...

A+
Commenter la réponse de la_gavorade
Utilisateur anonyme - 28 juin 2006 à 14:17
0
Merci
Bon vu le poste apres le tien, je tiens à intervenir ;) :

Si je t'ai vexé j'en suis navré. Sincèrement dans ma réponse, je souhaitais faire de l'humour en aucune facon te porter atteinte dans ton intégrité (qu'est ce que je parle bien en ce moment : j'ai eu des doigts tout neufs). Je me suis simplement permis de te signaler que tu avais donné trop d'infos : conséquences une grosse difficulté à analyser le probleme. Si je te l'ai signalé c'est que l'on puisse t'aider.

Effectivement j'ai un lien d'amitié avec Matt et d'autres membres actifs (JLen, Cirec,fOxi, Delphiprog, Florenth,Nico ect ect ect). Maintenant il peut m'arriver de me planter (et c'est vrai pour les autres) et de déraper : si tel est le cas, je peux t'assurer que je serai remis à ma place (et ca déjà été le cas) malgré l'amitié que l'on peut avoir entre nous (question d'honneté). Si Matt a posté ce message ce n'est pas (uniquement) par solidarité ou amitié mais parce qu'il n'avait rien de mal dans mes propos.

Par rapport à DelphiLab (Au fait merci de leur faire de la pub ^^), on m'a proposé d'y devenir Administrateur : décision que j'avais accepté puis enfin de compte décliné pour une question de loyauté envers CS (ce qui ne vas pas dire que je ne vais pas leur donné un coup de main : ;)). J'apprécie cette communauté et la respecte (donc toi aussi).

Désolé si je t'ai vexé. Reformule et recadre ta question et si je peux aider, je le ferai

A+
Commenter la réponse de Utilisateur anonyme
Utilisateur anonyme - 28 juin 2006 à 14:41
0
Merci
Une petite recherche sur Google (avec les mots : delphi+Handle+PostMessage) t'aurais expliquer le pourquoi du comment : http://tcharles.developpez.com/simul/?delphi=1.

... la fonction PostMessage() et l'utilisation de keybd_event() ne permet pas de limiter l'évènement à une application cible. Par ailleurs, une combinaison de ces deux fonction ne résoud pasle problème à coup sûr. Le problème vient du fait que la fonction PostMessage() n'attends pas que le message ai été traité par l'application cible avant de rendre la main à notre programme de contrôle. Pour parer à ce problème, on est obligé d'utiliser la fonction SendMessage() qui a le même prototype que PostMessage() mais qui attend que le message ai été traité pour rendre la main. Cependant, si l'application cible ne rend pas la main très rapidement il y a de grande chances pour que l'utilisateur appuye sur touche du clavier pendant ce laps de temps et on ne peut pas mesurer les conséquences de cette interférence. La seule solution qui nous reste est donc d'espèrer que l'utilisateur sera loin de son clavier au moment où on effectuera la simulation.

Il faut utiliser SendMessage : PostMessage est non bloquant. Voila déjà un début d'explication et un début de solution.

De plus je te conseille de faire un petit test : tu inverses des deux PostMessages. Et la tu aurais ciblé ton probleme réellement.

A+
Commenter la réponse de Utilisateur anonyme
la_gavorade
Messages postés
24
Date d'inscription
jeudi 22 juillet 2004
Dernière intervention
30 juin 2006
- 28 juin 2006 à 15:11
0
Merci
Merci Francky pour ces pistes.

Malheureusement, le post de GRrosminet que tu as mis en lien, c'est un des premiers trucs que je suis allé voir et que j'ai imprimé avant même de poster mon message sur le forum. C'est très bien fait, et ça m'a éclairci pas mal de trucs sur les simu clavier / souris.....mais même avec des SendMessage à la place des PostMessage ça marche toujours pas !
Et l'ajout à la fin de mon code d'un petit "ShowMessage('fin du test');" m'a malheureusement prouvé que le SendMessage n'est pas bloquant non plus dans mon cas, et rend la main très vite.
Il envoie donc la requête, mais je sais pas où, en tout cas pas vers la fenêtre Notepad...

???

A+, merci pour votre aide.
Commenter la réponse de la_gavorade
Utilisateur anonyme - 28 juin 2006 à 16:08
0
Merci
Re,

Peux tu essayer cela stp :

Test 1 :

Setforeground(handle_notepad) ; // Encore OK, la fenêtre Notepad est active
PostMessage(handle_notepad, WM_KEYDOWN, VK_DECIMAL, 0) ;
handle_notepad := findwindow('notepad', nil) ; //Instruction à rajouter
Sleep(2000); //On fait dodo
Application.ProcessMessages; //Mais pas profondément : ;).
PostMessage(handle_notepad, WM_KEYUP, VK_DECIMAL, 0) ;

Test 2 :
Setforeground(handle_notepad) ; // Encore OK, la fenêtre Notepad est active
PostMessage(handle_notepad, WM_KEYDOWN, VK_DECIMAL, 0) ;
handle_notepad := findwindow('notepad', nil) ; //Instruction à rajouter
PostMessage(handle_notepad, WM_KEYUP, VK_DECIMAL, 0) ;

Regarde ce que cela fait test et dis nous ce qu'il en résulte stp .

Merci A+
Commenter la réponse de Utilisateur anonyme
la_gavorade
Messages postés
24
Date d'inscription
jeudi 22 juillet 2004
Dernière intervention
30 juin 2006
- 28 juin 2006 à 17:03
0
Merci
Pas d'amélioration...

Pourtant j'ai espéré avec le Application.ProcessMessages, j'y avais pas pensé et c'était bien vu, mais malheureusement...ça vient pas de là.

Comprends pas...

Y'a pas d'erreur dans mes arguments du PostMessage, au moins ?
Commenter la réponse de la_gavorade
Utilisateur anonyme - 28 juin 2006 à 20:32
0
Merci
Juste 34 questions stp :

*La seconde méthode donne quoi ??

*Si tu inverses les PostMessage, il se passe quoi ??

*Peut tu légèrement modifier ton code et afficher dans un Label ou Edit, les Handles que tu récupère dans ce code :

Setforeground(handle_notepad) ; /
handle_notepad := findwindow('notepad', nil) ;
PostMessage(handle_notepad, WM_KEYDOWN, VK_DECIMAL, 0) ;
handle_notepad := findwindow('notepad', nil) ; /r
PostMessage(handle_notepad, WM_KEYUP, VK_DECIMAL, 0) ;

*As tu essayer de faire une boucle du type ?

While ...... do
Begin
Sleep;
Application.ProcessMessages;
end;
PostMessage(handle_notepad, WM_KEYUP, VK_DECIMAL, 0) ;

Merci à toi
Commenter la réponse de Utilisateur anonyme
DeltaFX
Messages postés
459
Date d'inscription
lundi 19 avril 2004
Dernière intervention
8 avril 2009
- 29 juin 2006 à 10:14
0
Merci
Et jeter un oeil sur le MSDN, ca tente personne ? Nan paske y a pas que PostMessage et SendMessage, non plus.....

SendMessageCallBack : The SendMessageCallback function sends the specified message to a
window or windows. It calls the window procedure for the specified window and
returns immediately. After the window procedure processes the message, the
system calls the specified callback function, passing the result of the message
processing and an application-defined value to the callback function.

SendMessageTimeOut :

LRESULT SendMessageTimeout(      
    HWND hWnd,
    UINT Msg,
    WPARAM wParam,
    LPARAM lParam,
    UINT fuFlags,
    UINT uTimeout,
    PDWORD_PTR lpdwResult
);

Parameters

* hWnd : [in] Handle to the window whose window procedure will receive the message.
If this parameter is HWND_BROADCAST, the message is sent to all top-level
windows in the system, including disabled or invisible unowned windows. The
function does not return until each window has timed out. Therefore, the total
wait time can be up to the value of uTimeout multiplied by the number of
top-level windows.

* Msg : Specifies the message to be sent.
* wParam : Specifies additional message-specific information.
* lParam : Specifies additional message-specific information.
* fuFlags : Specifies how to send the message. This parameter can be one or more of
the following values.
<dl> * : SMTO_ABORTIFHUNG</italique>Returns without waiting for the time-out period to elapse if the receiving
thread appears to not respond or \"hangs.\"
* : SMTO_BLOCK</gras></italique>Prevents the calling thread from processing any other requests until the
function returns.
* : SMTO_NORMAL</italique>The calling thread is not prevented from processing other requests while
waiting for the function to return.
* : SMTO_NOTIMEOUTIFNOTHUNG</italique>Microsoft Windows 2000/Windows XP: Does not return when the time-out period
elapses if the receiving thread stops responding.
</dd><dt>uTimeout</dt><dd>Specifies the duration, in milliseconds, of the time-out period. If the
message is a broadcast message, each window can use the full time-out period.
For example, if you specify a five second time-out period and there are three
top-level windows that fail to process the message, you could have up to a 15
second delay.
</dd><dt>lpdwResult</dt><dd>Receives the result of the message processing. This value depends on
the message sent.</dd></dl>Return Value

If the function succeeds, the return value is nonzero.

If the function fails or times out, the return value is zero. To get extended
error information, call GetLastError. If
GetLastErrorSendMessageTimeout returns zero, then the function timed out.
does not provide information about individual windows
timing out if HWND_BROADCAST is used.

RemarksThe function calls the window procedure for the specified window and, if the
specified window belongs to a different thread, does not return until the window
procedure has processed the message or the specified time-out period has
elapsed. If the window receiving the message belongs to the same queue as the
current thread, the window procedure is called directly—the time-out value is
ignored.

This function considers a thread is not responding if it has not called GetMessage
or a similar function within five seconds.
Commenter la réponse de DeltaFX
Cirec
Messages postés
4229
Date d'inscription
vendredi 23 juillet 2004
Dernière intervention
3 août 2018
- 29 juin 2006 à 11:09
0
Merci
Salut,
Recopier la page du MSDN n'apporte rien ...
un simple lien aurait suffit


la bonne question est : as-tu fais un teste avec SendMessageCallback 
la différence est dans la possibilité d'ajouter une function qui sera executé après le message


et si tu regardes mon poste tu verras que SendMessage fonctionne très bien mais pas avec WM_KEYDOWN et WM_KEYUP mais avec WM_CHAR et en plus le Handle qu'il utilisait n'était pas le bon

WM_KEYDOWN et WM_KEYUP sont à utiliser avec PostMessage


Et tout ce qui suit FONCTIONNE

<gras>Procedure
TForm1.Button2Click(Sender: TObject);
Var
  Wnd : THandle;
  I: Integer;
  S: String;
Begin
  //on récupère le Handle du NotePad
  Wnd := FindWindow('notepad', nil);
  // si NotePad à été trouvé ... 
  If Wnd <> 0 Then
  Begin
    // ... on récupère le Handle de l'Edit du NotePad
    Wnd : = FindWindowEx(Wnd, 0, 'Edit', nil);
    S := 'DelphiFR c''est Cool';
    For  I : = 1 To Length(S) Do
     //on envoie la chaine de caractères
      SendMessage(Wnd, WM_CHAR, Word(s[i]), 0);
     // on termine par un point.
     PostMessage(Wnd, WM_KEYDOWN, VK_DECIMAL, 0);
     // On revient à la ligne avec Enter.
     PostMessage(Wnd, WM_KEYDOWN, VK_RETURN, 0);
     // et on place un Espace.
     PostMessage(Wnd, WM_KEYDOWN, VK_SPACE, 0);
  End;
End;

Voilà c'est tout














@+
Cirec
Commenter la réponse de Cirec
la_gavorade
Messages postés
24
Date d'inscription
jeudi 22 juillet 2004
Dernière intervention
30 juin 2006
- 30 juin 2006 à 14:35
0
Merci
Merci à tous pour votre aide.

Effectivement le pb était double : les WM_KEYUP et WM_KEYDOWN ne fonctionnent pas avec SendMessage, contrairement au WM_CHAR... Me demandez pas pourquoi, je trouve ça bizarre moi aussi.
Et également, il fallait aller chercher le handle de la fenêtre enfant de la fenêtre principale Notepad, et donc bien spécifier 'edit' en argument du FindWindowEx.

Comme ce prog avec notepad n'était qu'un test pour comprendre comment utiliser SendMessage avec une fenêtre non active, j'ai cependant dû également adapter le code pour l'utiliser avec les fenêtres enfant du programme que j'utilise, et dont je ne connais pas le ClassName à priori. L'aide du source EnumForms (http://www.delphifr.com/code.aspx?ID=16615) de Kenavo et l'ajout de quelques EnumChildWindows par-ci par-là m'ont permis d'enfin faire fonctionner ce prog sur mon serveur virtuel !!!
Victoire, et merci encore à tous. :-)
Commenter la réponse de la_gavorade
cs_mounjetado
Messages postés
69
Date d'inscription
lundi 13 mars 2006
Dernière intervention
4 août 2008
- 3 juil. 2006 à 11:09
0
Merci
euh je suis pas un cador mais...
y a pas une histoire de changement de priorité des threads qd on minimise une fenêtre, ou un truc de ce genre? une propriété peut-être, qui fait que ton prog es ten qq sorte mis en attente qd il n'est pas au premier plan? je crois avoir vu qqch comme ça...
mais bon je le répète, je ne suis pas un grand manitou ds le monde de la programmation
@+








<hr />

si Delphi m'était conté...
Commenter la réponse de cs_mounjetado

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.