la_gavorade
Messages postés23Date d'inscriptionjeudi 22 juillet 2004StatutMembreDernière intervention30 juin 2006
-
27 juin 2006 à 14:52
cs_mounjetado
Messages postés66Date d'inscriptionlundi 13 mars 2006StatutMembreDerniè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 :
// 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...
Cirec
Messages postés3833Date d'inscriptionvendredi 23 juillet 2004StatutModérateurDernière intervention18 septembre 202250 28 juin 2006 à 18:55
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;
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)
la_gavorade
Messages postés23Date d'inscriptionjeudi 22 juillet 2004StatutMembreDernière intervention30 juin 2006 27 juin 2006 à 16:32
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 ???
la_gavorade
Messages postés23Date d'inscriptionjeudi 22 juillet 2004StatutMembreDernière intervention30 juin 2006 28 juin 2006 à 11:51
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 ?
Matt 261
Messages postés1173Date d'inscriptionmercredi 2 novembre 2005StatutMembreDernière intervention10 septembre 20113 28 juin 2006 à 12:01
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.
la_gavorade
Messages postés23Date d'inscriptionjeudi 22 juillet 2004StatutMembreDernière intervention30 juin 2006 28 juin 2006 à 14:05
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...
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
... 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.
la_gavorade
Messages postés23Date d'inscriptionjeudi 22 juillet 2004StatutMembreDernière intervention30 juin 2006 28 juin 2006 à 15:11
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...
DeltaFX
Messages postés449Date d'inscriptionlundi 19 avril 2004StatutMembreDernière intervention 8 avril 20092 29 juin 2006 à 10:14
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.
* 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.
Cirec
Messages postés3833Date d'inscriptionvendredi 23 juillet 2004StatutModérateurDernière intervention18 septembre 202250 29 juin 2006 à 11:09
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;
cs_mounjetado
Messages postés66Date d'inscriptionlundi 13 mars 2006StatutMembreDernière intervention 4 août 2008 3 juil. 2006 à 11:09
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
@+