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

Windows Discussion :

un hook pour le clavier


Sujet :

Windows

  1. #1
    Membre averti
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Points : 387
    Points
    387
    Billets dans le blog
    3
    Par défaut un hook pour le clavier
    Bonjour à tous,
    j'ai un ptit bonhomme appelé joe qui se balade dans une fenêtre grâce aux touches fléchées du clavier; l'étape suivante consiste à balader joe sur l'écran entier !
    Problème : Comment gérer le déplacement de joe avec le clavier puisque il n'existe pas de fenêtre associée qui reçoit les messages ?
    Alors j'ai pensé aux" Hooks" permettant le "crochetage" des messages!!
    Malheureusement , ce qui me semblait évident -- création du hook avec
    SetWindowsHookEx() ,gestion des messages clavier dans la procédure de hook --- ne l'ai en fait pas du tout ; en bref je n'ai visiblement rien pigé !!
    De plus , la littérature sur le sujet est assez absconse et peu claire .
    Quelqu'un aurait-il un conseil où un exemple BIEN précis sur le sujet ?
    merci.

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 685
    Points : 13 102
    Points
    13 102
    Par défaut
    La méthode à privilégier serait Raw Input. Les hooks sont de moins en moins apprécié. Un exemple en Delphi ici.

    Par hook, il faut déjà distinguer les deux types : standard, bas niveau.

    Standard:
    Enregistré par WH_KEYBOARD. Le hook doit obligatoirement être dans une DLL qui sera injectée dans chaque processus.

    Avantages :
    • rapidité ;
    • en cas de problème dans le hook, seul le processus impliqué risque le deadlock.

    Inconvénient :
    • le partage des données, surtout depuis l'arrivée de l'UAC et du niveau d'intégrité.


    Bas niveau (Low Level):
    Enregistré par WH_KEYBOARD_LL. Le hook peut être indifféremment dans l'exe ou une DLL (même si la littérature voudrait qu'il soit aussi dans une DLL). Il y a commutation de processus ; le code sera toujours exécuté dans celui de ton application.

    Avantages :
    • exe sans dll ;
    • un seul espace mémoire, donc partage des données facilité ;

    Inconvénients :
    • plus lent dû à la commutation ;
    • risque de deadlock du système complet (XP) ;
    • depuis Vista, déchargement du hook par le système en cas de problème ou de traitement trop long (évite le deadlock) mais sans aucune forme de notification !


    Dans les deux cas, le traitement du hook doit être le plus rapide possible sous peine de ralentir le système. Les mieux est d'uniquement filtrer les messages et de renvoyer les informations intéressantes par PostMessage. En Delphi, quelque chose comme ceci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function KeyBoardLLProc(Code: integer; wParam: WPARAM; lParam: LPARAM):LRESULT; stdcall;
    begin
      if (Code >= HC_ACTION) then
      begin
        if MesConditions then
        begin
          PostMessage(MaFenêtre, MonMessage, 0, 0);
        end;
      end;
    
      Result := CallNextHookEx(0, Code, wParam, lParam);
    end;

  3. #3
    Membre averti
    Avatar de exe2bin
    Profil pro
    Passionné de programmation
    Inscrit en
    Mars 2009
    Messages
    537
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Passionné de programmation

    Informations forums :
    Inscription : Mars 2009
    Messages : 537
    Points : 387
    Points
    387
    Billets dans le blog
    3
    Par défaut
    Merci pour ta réponse.
    Une précision toutefois : dans cette application il n'y a pas de fenêtre et encore moins de procédure de fenêtre ,pourquoi faire d'ailleurs puisque l'affichage doit se faire sur l'écran du bureau ?
    Ensuite ,est-il obligatoire de poster un message à la procédure de fenêtre dans le hook ?!
    De même est-il nécessaire d'appeler CallNextHook() ?
    Tu l'auras compris je débute en programmation ; ce qui me faudrait c'est un bon tuto là-dessus .

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 685
    Points : 13 102
    Points
    13 102
    Par défaut
    La fenêtre peut très bien être "message-only" (sans visuel).
    Non, il n'est pas obligatoire de passer par un PostMessage mais comme je te l'ai dit, le traitement du hook doit être le plus rapide possible. En envoyant un message asynchrone, il est immédiatement libéré. Ton application elle, peut prendre son temps

    CallNextHookEx est obligatoire à moins que tu veuilles "manger" le message. Les hooks installés sont chaînés et c'est cette fonction qui appelle le hook suivant.

    Tu as pourtant ici des exemples complets. Si tu disais plutôt ce qui se passe, ça nous aiderait
    ps: à noter que ces exemples sont plutôt ancien. Le premier paramètre de CallNextHookEx peut être fixé à 0.

  5. #5
    Expert éminent sénior
    Avatar de Mat.M
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2006
    Messages
    8 360
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2006
    Messages : 8 360
    Points : 20 378
    Points
    20 378
    Par défaut
    Citation Envoyé par exe2bin Voir le message
    Problème : Comment gérer le déplacement de joe avec le clavier puisque il n'existe pas de fenêtre associée qui reçoit les messages ?
    A
    en programmation Windows et dans tous les langages il y a toujours une fenêtre associée qui reçoit les messages.
    Ou alors c'est un programme console

  6. #6
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Points : 2 605
    Points
    2 605
    Par défaut
    Bonjour.

    Je n'ai pas testé ce programme, mais il semble récupérer les évènements clavier. Et ni sans hook, ni sans fenêtre :

    http://tcharles.developpez.com/simul/

    Code C : 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
     
    #include <windows.h>
    int main(int argc, char *argv[])
    {
         POINT pt;
         BOOL bContinue = TRUE;
         const SHORT Mask = 32768;
         while (bContinue)
         {
              if (GetKeyState(VK_ESCAPE) & Mask)
                   bContinue = FALSE;
              GetCursorPos(&pt);
              if (GetKeyState(VK_UP) & Mask)
                   pt.y -= 1;
              if (GetKeyState(VK_DOWN) & Mask)
                   pt.y += 1;
              if (GetKeyState(VK_LEFT) & Mask)
                   pt.x -= 1;
              if (GetKeyState(VK_RIGHT) & Mask)
                   pt.x += 1;
              SetCursorPos(pt.x,pt.y);
              Sleep(10);
         }
         return 0;
    }

    Après, il est certainement nécessaire que ce programme nécessite d'avoir le focus, c'est-à-dire que s'il est en arrière-plan cela ne marche pas. J'imagine que GetKeyState ne fonctionne que pour l'application qui est en premier plan.

    Un article en .net sur le hook :

    http://humann.developpez.com/hook/

    Un autre en C/C++ :

    http://www.developpez.net/forums/d17...vier-sans-dll/

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 685
    Points : 13 102
    Points
    13 102
    Par défaut
    Citation Envoyé par moldavi Voir le message
    Je n'ai pas testé ce programme, mais il semble récupérer les évènements clavier. Et ni sans hook, ni sans fenêtre
    Non seulement le faire avec une boucle est très très laid mais il y a surtout beaucoup de chance pour que tu loupes des états

    Citation Envoyé par moldavi Voir le message
    c'est-à-dire que s'il est en arrière-plan cela ne marche pas
    Si, si. ça fonctionne.

  8. #8
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Avec GetKeyState(), ça fonctionne? Ça m'étonne, vu qu'il me semblait que GetKeyState() c'est l'état du clavier tel que transmis à la fenêtre... (par opposition à GetAsyncKeyState(), qui lit directement l'état global du clavier)
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

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

    Informations forums :
    Inscription : Septembre 2008
    Messages : 5 685
    Points : 13 102
    Points
    13 102
    Par défaut
    Disons que l'état est correct (stable) jusqu'à ce que le message ait été traité par l'application cible. C'est sûr qu'il est préférable d'utiliser GetAsyncKeyState depuis une application tiers.
    Par contre le bit Toggle est conservé.

Discussions similaires

  1. Hook pour récupérer le nom d'appli qui a le focus
    Par extenbrisadlucem dans le forum Gnome
    Réponses: 4
    Dernier message: 18/07/2008, 16h57
  2. Hook pour récupérer les messages windows d'une autre application
    Par Tuizi dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 07/12/2007, 15h30
  3. Layer pour un clavier de piano ?
    Par Suwabara dans le forum Graphisme
    Réponses: 2
    Dernier message: 24/06/2007, 23h24
  4. Quelle API pour le clavier et / ou les threads?
    Par BugFactory dans le forum Développement 2D, 3D et Jeux
    Réponses: 10
    Dernier message: 06/04/2007, 18h54
  5. dérivation CFormView pour raccourcis clavier.
    Par eomer212 dans le forum MFC
    Réponses: 2
    Dernier message: 15/01/2007, 14h19

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