IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Delphi Discussion :

Simuler un clic


Sujet :

Langage Delphi

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Août 2005
    Messages
    144
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 144
    Points : 47
    Points
    47
    Par défaut Simuler un clic
    Bonjour,

    Après recherche dans le forum j'ai trouvé un code pour lancer une appli
    sélectionner le handle du programme
    recherche un bouton dans le fenêtre
    et simuler l'appui.

    Cela fonctionne

    Sauf que l'appli définitive est acces avec une macro. Quand je lance l'icône, il y a une fenêtre de login.

    Etant une fenêtre fille le problème est peuêtre là car je recherche le handle de cette fenêtre par son nom et rien se passe.

    Merci popur vos idées.

    Laurent

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Août 2005
    Messages
    144
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 144
    Points : 47
    Points
    47
    Par défaut
    J'ai avancé dans mon problème.

    La fenêtre fille avec sont bouton ok pas de problème.

    Une fois connecté, j'ai une fenêtre pour qui la sélection est bien faite avec dedans différents bouton.

    Importer
    Réglage
    Sortie

    J'ai essayé de simuler le clic sur tous ces boutons, aucun n'est trouvé.

    La fonction FindWindowEx me retourne toujours 0

    Est-ce qu'il y a un moyen de retrouver le nom de ces boutons, y a t il un problème avec access

    Merci pour votre aide.

    Laurent

  3. #3
    Membre éclairé
    Profil pro
    Développeur Java
    Inscrit en
    Mars 2004
    Messages
    624
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Mars 2004
    Messages : 624
    Points : 681
    Points
    681
    Par défaut
    FindWindowEx ne retoure que les conteneur (Form ou Panel).

    En suivant ce tutoriel
    on déduit le code suivant :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    var
      Tray, Child : hWnd;
      C : Array[0..127] of Char;
    Begin
     Tray := FindWindow(nom_de_la_fenêtre, NIL);
     Child := GetWindow(Tray, GW_CHILD);
     While Child <> 0 do Begin
      If GetClassName(Child, C, SizeOf(C)) > 0 Then Begin
       If UpperCase(StrPAS(C)) = 'BUTTON'Then Begin
        // instructions
       End;
      End;
      Child := GetWindow(Child, GW_HWNDNEXT);
     End;
    End;

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Août 2005
    Messages
    144
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 144
    Points : 47
    Points
    47
    Par défaut
    Ca ne change rien.

    Voici mon code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
     
    var
    hCible, hButton : HWND;
     
    begin
    winexec(pchar('"Mon programme"'),sw_show);
    application.ProcessMessages;
    sleep(2000);
     
    hCible := FindWindow(nil, PChar('Microsoft Access')); //on retrouve le Handle de la fenêtre du programme
    if hCible <> 0 then
    begin
    hCible := FindWindow(nil, PChar('Ouverture de session')); //on retrouve le Handle de la fenêtre du programme
    if hCible <> 0 then
    begin
      hButton := FindWindowEx(hCible, 0, nil, PChar('OK')); //on retrouve le Handle du bouton sur lequel on veux cliquer
      if hButton <> 0 then
        SendMessage(hButton, BM_CLICK, 0, 0); //on ( veut !) lui faire croire que l'on a cliqué dessus
     
    hCible := FindWindow(nil, PChar('CLIENT')); //on retrouve le Handle de la fenêtre du programme
    if hCible <> 0 then
    begin
      hButton := FindWindowEx(hCible, 0, nil, PChar('Sortie ')); //on retrouve le Handle du bouton sur lequel on veux cliquer
      if hButton <> 0 then
      begin
        SendMessage(hButton, BM_CLICK, 0, 0); //on ( veut !) lui faire croire que l'on a cliqué dessus
      end;
    END;
     end;
     end;
    end;
    Cela fonctionne jusqu'à la fenêtre CLIENT puisque je rentre sauf que findwindiwEx ne trouve pas le bouton sortie alors qu'il a trouvé OK

  5. #5
    Membre expert
    Avatar de LadyWasky
    Femme Profil pro
    Inscrit en
    Juin 2004
    Messages
    2 932
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 53
    Localisation : France, Hauts de Seine (Île de France)

    Informations forums :
    Inscription : Juin 2004
    Messages : 2 932
    Points : 3 565
    Points
    3 565
    Par défaut
    Télécharge le code de mon "démineur" dans la rubrique défi :
    http://delphi.developpez.com/defi/demineur/defieur/
    (profites en pour lire le chapitre II-A)

    Dans l'unité UnitSystem.pas, tu trouvera ton bonheur avec deux fonctions (MouseClickOnScreen et VirtualMouseClickOnWindow). La première procédure utilise la fonction de l'API mouse_event, la seconde utilise le sytème d'envoi de messages Windows classique avec PostMessage.

    Voici leur prototype :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    //Simulation du clic sur l'écran : cliques réellement (déplace la souris)
    procedure MouseClickOnScreen(Boutons:TMouseButtons;APoint: TPoint);
    //Simulation du clic sur l'écran : clic virtuel (ne déplace pas la souris)
    procedure VirtualMouseClickOnWindow(AWindowHandle:HWND;Boutons:TMouseButtons;APoint: TPoint);
    Le paramêtre AWindowHandle attend le Handle de la fenêtre sur laquelle on souhaite cliquer.

    Par ailleurs, dans cette unité, tu trouvera aussi des fonctions pour activer (mettre le focus) sur la fenêtre sur laquelle tu souhaite cliquer avec VirtualMouseClickOnWindow :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //Activation d'une fenètre (clic sur sa barre de titre)
    procedure ActiverFenetre(AHandle:HWND);
    Voici, dans le projet, un exemple d'utilisation, le programme ouvre tout seul le jeu de démineur, récupère le handle de fenêtre et simule l'appui sur les touches du clavier pour sélectionner le niveau choisi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    procedure TFormMain.DemarrerWinMine;
    var i:integer;
    begin
      //On cherche si démineur est déjà ouvert
      //(on récupère son Handle de fenètre au passage)
      WinMineHandle:=FindWindow(nil, PChar(WinMineWindowTitle));
      //si oui, on le ferme pour mettre à jour les scores
      if WinMineHandle<>0
      then begin
             FermerApplication(WinMineHandle);
             UpdateScores;
           end;
     
      ModeTriche:=False;
     
      { Mise à zéro de la structure StartInfo }
      FillChar(StartInfo,SizeOf(StartInfo),#0);
      { Seule la taille est renseignée, toutes les autres options }
      { laissées à zéro prendront les valeurs par défaut }
      StartInfo.cb     := SizeOf(StartInfo);
     
      { Lancement de la ligne de commande }
      CreateProcess(Nil, '"winmine.exe"', Nil, Nil, False,
                    0, Nil, Nil, StartInfo,ProcessInfo);
      //Attend que démineur soit lancé
      Sleep(1000);
      //on récupère le Handle sur la fenètre du démineur
      WinMineHandle:=FindWindow(nil, PChar(WinMineWindowTitle));
     
      //Activation/desactivation du mode triche ???
      if ((RadioGroupTriche.ItemIndex=0) and ModeTriche) then ActiveTriche;
      if ((RadioGroupTriche.ItemIndex=1) and (not ModeTriche)) then ActiveTriche;
     
      //on active la fenètre pour lui envoyer des codes touche
      ActiverFenetre(WinMineHandle);
     
      //on choisi le niveau = nouvelle partie
        //on ouvre le menu du démineur
        SimulateKeystroke(VK_MENU,0);
        //on descend dedans jusqu'à trouver le niveau souhaité
        for i:=1 to RadioGroupNiveau.ItemIndex+2 do
            SimulateKeystroke(VK_DOWN,0);
        //on valide
        SimulateKeystroke(VK_RETURN,0);
        //Attend que démineur soit prêt :
        Sleep(1000);
    end;

    TU y remarqueras cette ligne :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    //on récupère le Handle sur la fenètre du démineur
      WinMineHandle:=FindWindow(nil, PChar(WinMineWindowTitle));
    Qui récupère le Handle de la fenêtre du démineur en cherchant la dite fenêtre en fonction du titre de la fenêtre.
    WinMineWindowTitle est une constante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    unit UnitMineUtils;
     
    interface
    uses sysutils;
    Const
      //Titre de la fenètre du démineur
      WinMineWindowTitle='Démineur';
    ...
    Ce handle est utilisé plus tard dans le programme, par exemple ici (2 méthodes de clic sont présentées, selon l'optioon choisie par l'utilisateur) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    procedure TFormMain.MouseClickOnCase(Boutons:TMouseButtons;u, v: integer);
    begin
      if ModeSouris=mmRealClick
      then begin
             MouseClickOnScreen(Boutons,UVToScreen(u,v));
             Sleep(20); //tempo pour laissé le temps à Windows
                        //de digérer les clics de souris
           end
      else VirtualMouseClickOnWindow(WinMineHandle,Boutons,UVToClient(u,v));
    end;
    UVToScreen est juste une fonction qui transforme les coordonnés d'une case en coordonnées "écran", voici un exemple plus parlant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    procedure TFormMain.ReJouer;
    var x:integer;
        APoint:TPoint;
    begin
      //On clique sur le smiley ;)
     
      ScreenshotToZoneJeu;
      Application.ProcessMessages;
      //on teste le smiley :)
      x:=(ScreenShot.Width div 2)+2;
      APoint.x:=WinMineRect.Left+x;
      APoint.y:=WinMineRect.Top+25;
      Windows.ClientToScreen(WinMineHandle,APoint);
      MouseClickOnScreen(BoutonGauche,APoint);
    end;
    Ici, on sait où se trouve le bouton pour rejouer (on détermine ses coordonnées "fenêtre par le calcul"), puis on transforme les coordonnées "fenêtre" en coordonnée "écran" ( Windows.ClientToScreen(WinMineHandle,APoint); )

    Bref l'utilisation de l'API windows ClientToScreen est très utile pour cliquer là où il faut.
    Pour avoir les dimensions d'une zone cliente, tu peux utiliser ceci, ça peut être utile de le savoir aussi. :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    procedure TFormMain.InitZoneJeu;
    begin
      //La zone cliente du démineur
      Windows.GetClientRect(WinMineHandle,WinMineRect);
      ....
    end;

    Si tu ne sais pas où faire cliquer ton programme, il y a toujours moyen de s'arranger en simulant l'appui sur les bonnes touches, comme par exemple ici pour rentrer son nom lorsqu'on a un record :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    procedure TFormMain.RentreScore;
    begin
      SendKeys(EditNom.Text);
      SimulateKeystroke(VK_RETURN, 0);
      if SpinEditNbreParties.Value<=10 then
      begin
        Label1.Caption:='Admirez le score 3 secondes... Merci ;p';
        label1.Font.Color:=clRed;
        Application.ProcessMessages;
        Sleep(3000);
      end;
      sleep(100);
      Label1.Caption:=MessagesStatut[UnEtatDuJeu];
      label1.Font.Color:=clWindowText;
      SimulateKeystroke(VK_RETURN, 0)
    end;
    Et jettes un oeil dans la FAQ :
    http://delphi.developpez.com/faq/?pa...ulerclicsouris

    Si avec ça tu ne t'en sort pas...
    Bon dev

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Août 2005
    Messages
    144
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 144
    Points : 47
    Points
    47
    Par défaut
    Merci pour ces infos, sauf que dans mon cas, j'ouvre bien l'application,

    La fenêtre fille pour le login contient un bouton ok que j'arrive bien à sélectionner.

    Une fois logué, une autre fenêtre s'ouvre, la sélection fonctionne car le retour du handle n'est pas égal à 0.

    Après je n'arrive pas à simuler le clic pour les boutons.

    Comme si le nom dans le bouton affiché ne lui correspondait pas

  7. #7
    Membre expert
    Avatar de LadyWasky
    Femme Profil pro
    Inscrit en
    Juin 2004
    Messages
    2 932
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Âge : 53
    Localisation : France, Hauts de Seine (Île de France)

    Informations forums :
    Inscription : Juin 2004
    Messages : 2 932
    Points : 3 565
    Points
    3 565
    Par défaut
    Citation Envoyé par bremer Voir le message
    Merci pour ces infos, sauf que dans mon cas, j'ouvre bien l'application,
    Je n'ai rien compris à ce que tu veux dire.
    Ton programme lance l'application ? Bah le mien aussi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    { Mise à zéro de la structure StartInfo }
      FillChar(StartInfo,SizeOf(StartInfo),#0);
      { Seule la taille est renseignée, toutes les autres options }
      { laissées à zéro prendront les valeurs par défaut }
      StartInfo.cb     := SizeOf(StartInfo);
     
      { Lancement de la ligne de commande }
      CreateProcess(Nil, '"winmine.exe"', Nil, Nil, False,
                    0, Nil, Nil, StartInfo,ProcessInfo);
    OK, toi tu fais ça avec Winexec, mais c'est kifkif...

    Citation Envoyé par bremer Voir le message
    La fenêtre fille pour le login contient un bouton ok que j'arrive bien à sélectionner.

    Une fois logué, une autre fenêtre s'ouvre, la sélection fonctionne car le retour du handle n'est pas égal à 0.
    Donc tu obtiens au moins le handle de fenêtre, super !

    Citation Envoyé par bremer Voir le message
    Après je n'arrive pas à simuler le clic pour les boutons.

    Comme si le nom dans le bouton affiché ne lui correspondait pas
    Laisse tomber le handle du bouton, ça se trouve ce n'est pas un "TButton" mais plutot un "TBitButton" ou un "TSpeedButton" (je fais une analogie à la VCL de Delphi), ou bien ce bouton se trouve lui-^même dans un contrôle fenétré (une sorte de TPanel ou de TGroupbox par exemple ???) et tu auras du mal à récupérer un hadle sur ton bouton.
    A la place fait cliquer ta souris sur la fenêtre, aux coordonnées supposées du bouton, ça marchera aussi

  8. #8
    Expert éminent sénior
    Avatar de Jipété
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    10 851
    Détails du profil
    Informations personnelles :
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 10 851
    Points : 15 265
    Points
    15 265
    Par défaut
    Citation Envoyé par bremer Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    (...)
      hButton := FindWindowEx(hCible, 0, nil, PChar('Sortie ')); //on retrouve le Handle du bouton sur lequel on veux cliquer
    Cela fonctionne jusqu'à la fenêtre CLIENT puisque je rentre sauf que findwindiwEx ne trouve pas le bouton sortie alors qu'il a trouvé OK
    Y aurait pas une espace en trop, par hasard ('Sortie ') ? (ou alors c'est une erreur de colier-coller et j'ai rien dit).
    --
    jp

  9. #9
    Membre du Club
    Profil pro
    Inscrit en
    Août 2005
    Messages
    144
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 144
    Points : 47
    Points
    47
    Par défaut
    J'avais essayer les 2 mais rien à faire...

Discussions similaires

  1. Réponses: 11
    Dernier message: 04/01/2006, 23h57
  2. Réponses: 7
    Dernier message: 26/10/2005, 12h54
  3. Simuler un clic de souris
    Par kabikou dans le forum Access
    Réponses: 1
    Dernier message: 28/09/2005, 13h43
  4. Simulation de clic
    Par seiryujay dans le forum Agents de placement/Fenêtres
    Réponses: 7
    Dernier message: 31/08/2005, 17h05
  5. [JToggleButton] simuler un clic
    Par norkius dans le forum Composants
    Réponses: 4
    Dernier message: 30/05/2005, 16h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo