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 :

Création d'une macro clavier


Sujet :

Langage Delphi

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    25
    Détails du profil
    Informations personnelles :
    Âge : 76
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 25
    Points : 21
    Points
    21
    Par défaut Création d'une macro clavier
    Bonjour,
    Mon projet est de créer des macros claviers capable d'écrire de longues chaines par l'appui d'une touche ex: CTRL+ALT+touche alphanumérique.
    Grâce aux tutoriels du Forum, j'ai créé une DLL qui hameçonne les frappes clavier. Elle fonctionne bien.
    Dans mon programme, je capture les frappes de touches et je les affiche dans un mémo (pour mise au point). Jusque là pas de pb.
    A l'appui d'une touche (ici la touche B ), je désire envoyer une chaine de caractère qui sera reçue par une autre application quelconque.
    J'ai réussi à envoyer 1 caractères ex A . Quand j’appuie sur B il m'écrit bien A.
    là où cela se complique, c'est pour envoyer plusieurs caractères.
    Voici le code de la fonction:
    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
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
          PROCEDURE TForm3.OnWmCopyData(var Msg : TMessage);
     
       TYPE
          TPCopyDataStruct = ^TCopyDataStruct;
          TPDataEnvoyes    = ^TDataEnvoyes;
     
       VAR
          DataEnvoyes     : TDataEnvoyes;
          PDataEnvoyes    : TPDataEnvoyes;
          PCopyDataStruct : TPCopyDataStruct;
          KeyState        : TKeyState;
     
       BEGIN
          PCopyDataStruct := TPCopyDataStruct(Msg.LPARAM);
          PDataEnvoyes    := PCopyDataStruct^.lpData;
          DataEnvoyes     := PDataEnvoyes^;
          KeyState        := GetEtatTouche(DataEnvoyes.State);
          passkey         := DataEnvoyes.State;
          Keypressed      := KeyState.Pressed;
          Keyreaded       := DataEnvoyes.Key;
          IF (Keyreaded = ord('B')) AND (Keypressed) THEN
             Permission := NOT Permission;
          Msg.Result    := 1;
          IF (Permission) THEN
             Msg.Result := 0;
          { pour mise au point }
          if (Permission) then
          begin
             if NOT KeyState.PrevPressed then
                Memo1.Lines.Add('Clavier autorisé touche = ' + chr(Keyreaded));
     
             // Memo1.Lines.Add('Touche étendue = '+BoolToStr(KeyState.ExtendedKey)) ;
             // Memo1.Lines.Add('Touche ALT = '+BoolToStr(KeyState.Alt)) ;
             // Memo1.Lines.Add('Touche pressée auparavant = '+BoolToStr(KeyState.PrevPressed)) ;
             // Memo1.Lines.Add('');
     
          end else begin
             Memo1.Lines.Add('Clavier bloqué');
             Memo1.Lines.Add('');
             { si touche relachée : émettre un message }
             Permission := True;
             Msg.Result := 0;
             // keybd_event(ord('A'),0,0,0);
             EnvoiChaine(Msg, 'Hello world !');
             Msg.Result := 1;
          end;
     
       END; // ROCEDURE TForm3.OnWmCopyData
     
       { ---------------------------------------------------------------- }
     
       PROCEDURE TForm3.EnvoiChaine(var Msg : TMessage; s : String);
     
       var
          LongChaine, i : Integer;
          sChar         : Char;
     
       begin
          LongChaine := length(s);
          for i      := 1 to LongChaine do
          begin
             sChar := s[ i ];
             keybd_event(ord(sChar), 0, 0, 0);
             keybd_event(ord(sChar), 0, KEYEVENTF_KEYUP, 0);
             Sleep(10);
          end;
       end;
    et voici ce que j'obtiens (fichier joint) à droite mon mémo de contrôle, à gauche le résultat dans l'application.
    Si quelqu'un peut me donner un tuyau, grand merci.
    Images attachées Images attachées  

  2. #2
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 698
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 698
    Points : 13 137
    Points
    13 137
    Par défaut
    Tu ne nous dis pas où se trouve la difficulté, mais c'est certainement un problème de réentrance, d'où ce flag Permission. Il faut t'en passer

    Si tu utilises un hook de bas niveau, il est possible de savoir si le caractère est injecté (injected) et ainsi de ne pas faire suivre la touche à ton application.
    Par contre un WM_COPYDATA est beaucoup trop lent (synchrone) et depuis Vista, le hook risque d'être déchargé s'il prend trop de temps. Pour éviter un verrouillage du système (puisqu'il y a commutation de processus), l'OS décharge sans autre forme de procès (et sans aucune notification) les hooks de bas niveau dont la durée d'exécution est supérieure à environ 300 ms (temps global et non temps d'exécution réel du processus).

    Un hook standard est plus stable mais il n'y a pas directement la possibilité de savoir si la touche est injectée. Pour cela, il faudra prendre soin de passer cette information dans ExtraInfo.

    Une autre possibilité (la meilleure) est de se passer carrément de hook et d'utiliser des HOTKEYs (raccourcis clavier au niveau OS).

    Enfin, mieux vaut utiliser SendInput que Keybd_Event. SendInput remplit le buffer de clavier en une passe alors que l'appui sur une touche physique va interférer entre deux Keybd_Event.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    25
    Détails du profil
    Informations personnelles :
    Âge : 76
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 25
    Points : 21
    Points
    21
    Par défaut Création d'une macro clavier
    u ne nous dis pas où se trouve la difficulté, mais c'est certainement un problème de réentrance
    Justement, je n'ai pas trouvé! De plus le pas à pas de Delphi bloque Windows!

    Ce que je ne comprends pas c'est que la première lettre (H) est bien reçue par l'application cible alors que les caractères suivants se trouvent remplacés par "5/ /4" ???
    D'autre part, qu'entends tu par Hook standard ?

    Puis-je vraiment utiliser des Hotkey pour écrire dans une autre application qui détient le focus ?

    Enfin, je vais tester SendInput.
    Merci pour ta réponse, je tiens le forum au courant.

  4. #4
    Rédacteur/Modérateur
    Avatar de Andnotor
    Inscrit en
    Septembre 2008
    Messages
    5 698
    Détails du profil
    Informations personnelles :
    Localisation : Autre

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 698
    Points : 13 137
    Points
    13 137
    Par défaut
    Ah ok ! C'est un problème de compréhension du fonctionnement de Keybd_Event.

    Citation Envoyé par cataclysme Voir le message
    Justement, je n'ai pas trouvé! De plus le pas à pas de Delphi bloque Windows!
    Ce qui est logique avec un hook de bas niveau puisque toute frappe (physique ou simulée) entraîne la commutation dans ton processus que tu as... bloqué par un point d'arrêt

    Citation Envoyé par cataclysme Voir le message
    Ce que je ne comprends pas c'est que la première lettre (H) est bien reçue par l'application cible...
    Pas vraiment puisque tu envoies un "H" et que tu reçois un "h"
    Ce que tu n'as pas compris est que tu dois te conformer à la langue du clavier en cours. "H" existe (un scancode y est associé), mais "e" n'existe pas. Seules les majuscules sont définies et c'est l'état du shift qui détermine le caractère final. Ce n'est pas si simple !
    Pour envoyer ton texte correctement, tu devrais générer : Shift+H E L L O (tout en majuscule)

    SendInput permet lui de travailler directement en unicode en spécifiant KEYEVENTF_UNICODE. Il n'y a plus ce soucis de localisation du clavier et là tu peux y passer ton texte réel.

    Citation Envoyé par cataclysme Voir le message
    Puis-je vraiment utiliser des Hotkey pour écrire dans une autre application qui détient le focus ?
    Non, son but est simplement d'éviter l'utilisation d'un hook. SendInput subsiste.

    WH_KEYBOARD_LL : Bas niveau, commutation de processus.
    WH_KEYBOARD : standard, injectée dans chaque processus.

Discussions similaires

  1. Création d'une macro avec un paramètre
    Par jacklafrip dans le forum C
    Réponses: 4
    Dernier message: 19/02/2008, 21h35
  2. Création d'une macro sur bouton
    Par guenfood dans le forum IHM
    Réponses: 1
    Dernier message: 13/12/2007, 17h06
  3. Création d'une macro qui remplira un agenda
    Par Cyriusix dans le forum VBA Word
    Réponses: 21
    Dernier message: 07/12/2007, 11h28
  4. Création d'une macro mais erreur
    Par guismoman33 dans le forum Macros et VBA Excel
    Réponses: 10
    Dernier message: 04/06/2007, 18h14
  5. {EXCEL ou VBA}Création d'une macro (Débutant)
    Par Thomas69 dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 29/05/2007, 15h32

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