Utilisation de DoEvents pour reprendre la main sur une appli VB

Signaler
Messages postés
33
Date d'inscription
lundi 21 janvier 2008
Statut
Membre
Dernière intervention
28 novembre 2011
-
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
-
Salut tout le monde!!
J'ai un petit souci avec une application VB que je suis en train de développer, dont le but est de répéter une séquence de raccourci clavier à une fenêtre précise sous windows. Mon pbm principal est que je perds la main sur mon application VB dès lors qu'une procédure est en cours.....
Le code source de ma procédure associée à un button_click:<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" /??>

************************************************************************

Private Sub Command1_Click()

Dim i As Integer                                        ' index de ma boucle for, nb_repet est le nbre de répétition à effectuer

lres = SetForegroundWindow(handle_wd1)

For i = 1 To nb_repet

    Call keybd_event(VK_F2, 0, 0, 0)

    Call keybd_event(VK_F2, 0, KEYEVENTF_KEYUP, 0)

    Sleep 30000

Next

End Sub

*************************************************************************

La fonction de cette procédure est d'envoyer en boucle l'évènement clavier F2 à la fenêtre d'une application différente (application sous SAP), que j'active en début de procédure avec l'API 'SetForegroundWindow' afin d'automatiser une tâche extrêment simple mais à effectuée beaucoup de fois (entre 5 et 150 fois....).

Sachant qu'à partir du moment où l'appuie sur la touche F2 a été simulé, la tâche exécutée sous l'application prend un temps variable allant de 15 à 25 secondes. Ainsi, que le processus engendré par l'appuie de F2 dure 25 seconde ou moins, il y aura toujours ma temporisation de 30 secondes, ce qui implique une perte de temps....

 

J'ai donc une première question: existe-t-il un témoin quelque part ou une API particulière permettant de m'affranchir de ma temporisation Sleep,  afin de piloter l'incrémentation de mon index i à l'intérieur de ma boucle For avec un indicateur de fin du processus associé à un précédent appuie sur F2?  (J'espère que ce que je raconte est claire et compréhensible...) J'avais pensé au son wue Windows génère quand la tâche est terminée... Je me suis dis que ce son est tracée dans une varibale et que pour que ce sont soit généré à la fin de la tache il doit bien y avoir quelque part une variable indicatrice de fin de processus?!!!

 

Une deuxième question est liée au souhait d'ajouter un bouton pour interrompre ma boucle, j'ai lu qu'il y avait un moyen de redonner la main à Windows avec une certine fonction DoEvents,  cependant je ne suis pas sur d'avoir bien compris son fonctionnement... De ce dont j'en ai compris j'ai modifié mon code de la facon suivante, en utilisant une variable booléenne associée à un évènement command2_click():

 

*************************************************************************

Dim interrupt_ask As Boolean

 

Private Sub Command1_Click()

Dim i As Integer                                      ' index de ma boucle for, nb_repet est le nbre de répétition à effectuer

interrupt_ask = False                                   

For i = 1 To nb_repet

            DoEvents                        'donner la main à windows pour permettre la gestion de l'appuie sur bouton interrompre

            If interrupt_ask = True Then      ' qui est associé à la procédure Command2_Click()

                        interrupt_ask = False   ' si l'évènement interrompre à eu lieu on réinitialise la variable booléènne et on sort

                        Exit For                                  ' de la boucle For'

            EndIf

            lres = SetForegroundWindow(handle_wd1)  'donne le focus sur la fenêtre de l'appli SAP pour lui envoyer les evts clavier

    Call keybd_event(VK_F2, 0, 0, 0)

    Call keybd_event(VK_F2, 0, KEYEVENTF_KEYUP, 0)

    Sleep 30000                     ' attendre 30 seconde pour être sur que la tâche associée au F2 généré précédemment est bien terminée

Next

End Sub

 

Private Sub Command2_Click()

            interrupt_ask = True

EndSub

**************************************************************************

 Cependant, ca ne marche pas, à partir du moment ou je lance la boucle je perds complètement la main jusqu'à la fin de la boucle. L'icône de la souris est constamment doublé du petit sablier lorsque je plcae mon curseur sur l'application "Séquence_clavier" et si je tente de cliquer sur le bouton interrompre le message  "(ne répond pas)" vient s'accoler à côté de du nom de mon application dans la barre de titre.... Je suis donc obligé de terminé le processus en passant par le gestionnaire de tache CTRL+MAJ+ECHAP et de faire Applications>Fin de Tache pour sortir du programme.... Pas très classe ni très pro me direz vous...

 

Je voudrais joindre a feuille VB6 afin que vous puissiez faire le test vous même... Mais je ne sais pas ou est ce que l'on peut attacher un fichier sous ce forum... Pouvez vous m'aider? Après vous pourrez faire le test comme suis :Pour faire le test ave l'application calculatrice de Windows, vous devez lancer la calculatrice, récupérer le hWnd de la calculatrice à l'aide du bouton "Voir les fenêtres", renseigner le champs ID Wnd treated, donner le nombre de répétition de l'appuie de la touche F10 (ici je tavail avec F10 plutot qu'avec F2, car F2 n'a pas d'effet sous la calculatrice. En revanche F10 surligne/désurligne en bleu l'onglet "Edition" du menu de la calculatrice...). J'ai aussi modifié la durée du sleep pour accélerer la boucle et voir les effets à une échelle  de temps d'attente plus acceptable dans le cadre d'une procédure de débuggage...

 

J'ai une certine intuition quand à l'origine du bloquage mais je n'en suis pas certain... Pour moi il ya a une histoire de changement de handle perturbé/non gérer par mon application: en effet lorsque je clique (enfin plutot lorsque que je veux cliquer sur le bouton interrompre, cela implique que le l'envoi des séquences F2 s'applique à mon application et non plus à la fenêtre que je désire... Et j'arrive donc à ma troisième question: est il possible verrouiller un handle sur une fenêtre précise afin que la séquence clavier s'applique à une fenêtre spécifique, que je clique ou non sur une autre fenêtre, et donc que je fasse passer ma fenêtre en second plan...

 

7 réponses

Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
62
Sleep bloque ton appli.
donc faut cliquer au bon moment, pour que ca soit pris en compte ^^

fais un plus petite pause, mémorise le résultat de l'API GetTickCount
après avoir fait ton envoi de touche
ensuite, tu boucle tans qu'un certain temps n'est pas passé (GetTickCount - nStartTime > 30 ) ...
Messages postés
33
Date d'inscription
lundi 21 janvier 2008
Statut
Membre
Dernière intervention
28 novembre 2011

SAlut,
Merci pour ta réponse Renfield! Je pense que je vais abandonner la solution sleep qui est très simpliste au début mais qui me complique pas mal la tâche... Je cherche donc une autre solution qu'une temporisationqui me fait perdre du temps car l'évènement généré par F2 dure un temps variable lors que ma temporisation est fixée sur une variable précise... Je cherche donc à trouver un moyen de remplacer le sleep par une variable témoin de la fin de l'évènement généré par le F2 précédent... Sais tu s'il existe une api permettant d'être averti lors de la fermeture d'une fenêtre? J'avais pensé au son généré par windows lorsque la tâche est terminé....
A+
Messages postés
114
Date d'inscription
lundi 15 avril 2002
Statut
Membre
Dernière intervention
1 juillet 2011

Salut,

Est ce que tu na ps moyen de voir le handel de la fenetre ou sont nom, et de boucler sur l'ensemble des fenetre pour voir si elle existe, si elle n'es plus la ... le traitement est terminer,

a++
seb

Développement Rapide PHP / VBNET -> www.database2code.com
Messages postés
33
Date d'inscription
lundi 21 janvier 2008
Statut
Membre
Dernière intervention
28 novembre 2011

Carrément!!!!!!!!! J'y avais vraiment pas pensé!!!!! Merci aserf!!!! J'essaye cela ce soir et je te tiens au courant!!!!
Messages postés
33
Date d'inscription
lundi 21 janvier 2008
Statut
Membre
Dernière intervention
28 novembre 2011

Salut Aserf,

J'ai creusé du côté de ta proposition qui est vraiment astucieuse cependant je me vois dans l'impossibilité de la mettre en oeuvre vu que la fenêtre en question ne se ferme pas à la fin de la tâche.
 
En revanche j'ai constaté qu'il y a un message qui apparait à la fin de la tâche en bas de la fenêtre principale de l'application, dont le contenu est différent à chaque fois (car en rapport avec l'objet traité par la tâche). Le message apparait en bas de la fenêtre, dans une zone que j'appelerai la barre de dialogue. Je voudrais savoir si il existe une quelconque API windows me permettant de récupérer ce message dans une variable, sachant que je dispose du handle de cette fenêtre??? J'avais pensé à GetWindowText mais il semble que je ne peux récupérer que "le titre d'une fenêtre, d'un contrôle ou d'une zone de saisie".

Merci pour ton aide! Je continue à creuser de mon côté...
A+
roland
Messages postés
33
Date d'inscription
lundi 21 janvier 2008
Statut
Membre
Dernière intervention
28 novembre 2011

Bon, ca avnce plutôt bien!!! si ca vous intéresse j'ai trouvé des infos sur cette adresse http://209.85.229.132/search?q=cache:JRDM3XNEfkcJ:camernet.ifrance.com/vb/subclass.htm+API+message+barre+d%27%C3%A9tat&hl=fr&ct=clnk&cd=7&gl=fr




C'est un tutoriel sur le subclassing (ou sous classement) pour intercepter les messages windows. Il est vraiment bien fait, en plus en VB... Donc que du bonheur.... Je pense que je suis pas loin de trouver la solution!!! Il semble que l'info de fin de tâche qui s'affiche dans la barre d'état de ma fenêtre SAP est bien récupérable!!!!
Merci encore!!!
A+
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
62