Considérons un instant la création d'un jeu d'arcade rapide. Tous les graphiques sont affichés, disons, dans une TPainBox. TPaintBox ne peut pas recevoir le focus d'entrée - aucun événement n'est déclenché lorsque l'utilisateur appuie sur une touche; nous ne pouvons pas intercepter les touches du curseur pour déplacer notre cuirassé. Aide Delphi!
La plupart des applications Delphi gèrent généralement les entrées utilisateur via des gestionnaires d'événements spécifiques, ceux qui nous permettent de capturer les frappes des utilisateurs et de traiter les mouvements de la souris..
Nous savons que l'accent est mis sur la capacité de recevoir les commentaires des utilisateurs via la souris ou le clavier. Seulement le l'objet qui a le focus peut recevoir un événement clavier. Certains contrôles, tels que TImage, TPaintBox, TPanel et TLabel ne peuvent pas recevoir le focus. Le but principal de la plupart des contrôles graphiques est d'afficher du texte ou des graphiques.
Si nous voulons intercepter l'entrée du clavier pour les contrôles qui ne peuvent pas recevoir le focus d'entrée, nous devrons traiter avec l'API Windows, les crochets, les rappels et les messages.
Techniquement, une fonction "hook" est une fonction de rappel qui peut être insérée dans le système de messagerie Windows afin qu'une application puisse accéder au flux de messages avant qu'un autre traitement du message n'ait lieu. Parmi de nombreux types de hooks Windows, un hook clavier est appelé chaque fois que l'application appelle la fonction GetMessage () ou PeekMessage () et qu'il y a un message clavier WM_KEYUP ou WM_KEYDOWN à traiter.
Pour créer un crochet clavier qui intercepte toutes les entrées clavier dirigées vers un thread donné, nous devons appeler SetWindowsHookEx Fonction API. Les routines qui reçoivent les événements clavier sont des fonctions de rappel définies par l'application appelées fonctions de raccordement (KeyboardHookProc). Windows appelle votre fonction de raccordement pour chaque message de frappe (touche haut et touche bas) avant que le message ne soit placé dans la file d'attente de messages de l'application. La fonction de raccordement peut traiter, modifier ou supprimer des frappes. Les crochets peuvent être locaux ou mondiaux.
La valeur de retour de SetWindowsHookEx est une poignée pour le crochet qui vient d'être installé. Avant de terminer, une application doit appeler le UnhookWindowsHookEx fonction pour libérer les ressources système associées au hook.
En guise de démonstration des crochets de clavier, nous allons créer un projet avec contrôle graphique pouvant recevoir des pressions de touches. TImage est dérivé de TGraphicControl, il peut être utilisé comme surface de dessin pour notre jeu de bataille hypothétique. Étant donné que TImage n'est pas en mesure de recevoir des pressions sur le clavier via des événements de clavier standard, nous allons créer une fonction de crochet qui intercepte toutes les entrées de clavier dirigées vers notre surface de dessin.
Démarrez un nouveau projet Delphi et placez un composant Image sur une fiche. Définissez la propriété Image1.Align sur alClient. C'est tout pour la partie visuelle, maintenant nous devons faire du codage. Tout d'abord, nous aurons besoin de quelques variables globales:
var
Form1: TForm1;
KBHook: HHook; ceci intercepte la saisie au clavier
cx, cy: entier; suivre la position du navire de bataille
déclaration de rappel
function KeyboardHookProc (Code: Integer; WordParam: Word; LongParam: LongInt): LongInt; stdcall;
la mise en oeuvre
…
Pour installer un hook, nous appelons SetWindowsHookEx dans l'événement OnCreate d'un formulaire.
procédure TForm1.FormCreate (Sender: TObject);
commencer
Réglez le crochet du clavier afin que nous puissions intercepter la saisie au clavier
KBHook: = SetWindowsHookEx (WH_KEYBOARD,
rappel> @KeyboardHookProc,
HInstance,
GetCurrentThreadId ());
placez le vaisseau de bataille au milieu de l'écran
cx: = Image1.ClientWidth div 2;
cy: = Image1.ClientHeight div 2;
Image1.Canvas.PenPos: = Point (cx, cy);
fin;
Pour libérer les ressources système associées au hook, nous devons appeler la fonction UnhookWindowsHookEx dans l'événement OnDestroy:
procédure TForm1.FormDestroy (expéditeur: TObject);
commencer
décrochez l'interception du clavier
UnHookWindowsHookEx (KBHook);
fin;
La partie la plus importante de ce projet est la Procédure de rappel KeyboardHookProc utilisé pour traiter les frappes.
function KeyboardHookProc (Code: Integer; WordParam: Word; LongParam: LongInt): LongInt;
commencer
cas WordParam de
vk_Space: effacer le chemin du vaisseau de bataille
commencer
avec Form1.Image1.Canvas do
commencer
Brush.Color: = clWhite;
Brush.Style: = bsSolid;
Fillrect (Form1.Image1.ClientRect);
fin;
fin;
vk_Right: cx: = cx + 1;
vk_Left: cx: = cx-1;
vk_Up: cy: = cy-1;
vk_Down: cy: = cy + 1;
fin; Cas
Si cx < 2 then cx := Form1.Image1.ClientWidth-2;
Si cx> Form1.Image1.ClientWidth -2 alors cx: = 2;
Si cy < 2 then cy := Form1.Image1.ClientHeight -2 ;
Si cy> Form1.Image1.ClientHeight-2 alors cy: = 2;
avec Form1.Image1.Canvas do
commencer
Pen.Color: = clRed;
Brush.Color: = clYellow;
TextOut (0,0, Format ('% d,% d', [cx, cy]));
Rectangle (cx-2, cy-2, cx + 2, cy + 2);
fin;
Résultat: = 0;
Pour empêcher Windows de passer les frappes à la fenêtre cible, la valeur du résultat doit être une valeur différente de zéro.
fin;
C'est ça. Nous avons maintenant le code de traitement clavier ultime.
Notez juste une chose: ce code n'est en aucun cas limité à être utilisé uniquement avec TImage.
La fonction KeyboardHookProc sert de mécanisme général de KeyPreview et KeyProcess.