Interceptarea intrării tastaturii cu Delphi

Luați în considerare pentru o clipă crearea unor jocuri arcade rapide. Toate graficele sunt afișate, să zicem, într-un TPainBox. TPaintBox nu este în măsură să primească focalizarea de intrare - niciun eveniment nu este tras atunci când utilizatorul apasă o tastă; nu putem intercepta tastele cursorului pentru a ne deplasa nava de luptă. Ajutor Delphi!

Introducerea tastaturii de interceptare

Cele mai multe aplicații Delphi gestionează de obicei intrarea utilizatorului prin intermediul unor manageri de evenimente specifice, cele care ne permit să surprindem tastele utilizatorului și să procesăm mișcarea mouse-ului.

Știm că focalizarea este abilitatea de a primi inputul utilizatorului prin intermediul mouse-ului sau tastaturii. Doar obiectul focalizat poate primi un eveniment de la tastatură. Unele controale, cum ar fi TImage, TPaintBox, TPanel și TLabel nu pot primi focus. Scopul principal al majorității controalelor grafice este afișarea de text sau grafică.

Dacă dorim să interceptăm introducerea tastaturii pentru controale care nu pot primi focalizarea de intrare, va trebui să ne ocupăm de API-ul Windows, cârlige, apeluri de apel și mesaje.

Cârliguri de Windows

Tehnic, o funcție "hook" este o funcție de returnare care poate fi introdusă în sistemul de mesaje Windows, astfel încât o aplicație poate accesa fluxul de mesaje înainte de a avea loc alte prelucrări ale mesajului. Printre multe tipuri de cârlige Windows, este apelat un cârlig de tastatură ori de câte ori aplicația apelează funcția GetMessage () sau PeekMessage () și există un mesaj de tastatură WM_KEYUP sau WM_KEYDOWN pentru procesare.

Pentru a crea un cârlig de tastatură care interceptează toate intrările tastaturii direcționate către un thread dat, trebuie să apelăm SetWindowsHookEx Funcția API. Rutinele care primesc evenimentele de pe tastatură sunt funcții de apelare definite de aplicație numite funcții de cârlig (KeyboardHookProc). Windows apelează funcția dvs. de cârlig pentru fiecare mesaj de apăsare a tastei (tasta în sus și tasta în jos) înainte ca mesajul să fie plasat în coada de mesaje a aplicației. Funcția de cârlig poate prelucra, modifica sau arunca apăsările de taste. Cârligele pot fi locale sau globale.

Valoarea de returnare a SetWindowsHookEx este un mâner al cârligului tocmai instalat. Înainte de încheiere, o cerere trebuie să apeleze la UnhookWindowsHookEx funcție pentru a elibera resursele de sistem asociate cu cârligul.

Exemplu de cârlig pentru tastatură

Ca o demonstrație de cârlige de tastatură, vom crea un proiect cu control grafic care poate primi apăsări de taste. TImage este derivat din TGraphicControl, poate fi folosit ca suprafață de desen pentru jocul nostru de luptă ipotetic. Deoarece TImage nu este în măsură să primească prese de la tastatură prin evenimente standard de la tastatură, vom crea o funcție de cârlig care interceptează intrarea tastaturii îndreptată către suprafața noastră.

TImage Processing Process Keyboard Events

Începeți noul Delphi Project și așezați o componentă Imagine pe un formular. Setați proprietatea Image1.Align la alClient. Asta e pentru partea vizuală, acum trebuie să facem niște codări. În primul rând, vom avea nevoie de câteva variabile globale:

 var
  Form1: TForm1;
  KBHook: HHook; aceasta interceptează introducerea tastaturii
  cx, cy: întreg; urmează poziția navei de luptă
  declarație de returnare
  funcție KeyboardHookProc (Cod: Integer; WordParam: Word; LongParam: LongInt): LongInt; stdcall;
punerea în aplicare
...

Pentru a instala un cârlig, apelăm la SetWindowsHookEx în evenimentul OnCreate al unui formular.

 procedura TForm1.FormCreate (Expeditor: TObject);
începe
 Setați cârligul tastaturii pentru a putea intercepta introducerea tastaturii
 KBHook: = SetWindowsHookEx (WH_KEYBOARD,
           callback> @KeyboardHookProc,
                          HInstance,
                          GetCurrentThreadId ());
 așezați nava de luptă în mijlocul ecranului
 cx: = Image1.ClientWidth div 2;
 cy: = Image1.ClientHeight div 2;
 Image1.Canvas.PenPos: = Punct (cx, cy);
Sfârșit;

Pentru a elibera resursele de sistem asociate cu cârligul, trebuie să apelăm la funcția UnhookWindowsHookEx în evenimentul OnDestroy:

 procedura TForm1.FormDestroy (expeditor: TObject);
începe
  a deconectat interceptarea tastaturii
  UnHookWindowsHookEx (KBHook);
Sfârșit;

Partea cea mai importantă a acestui proiect este Procedura de apelare KeyboardHookProc folosit pentru procesarea apăsărilor de taste.

 funcție KeyboardHookProc (Cod: Integer; WordParam: Word; LongParam: LongInt): LongInt;
începe
 cazul WordParam din
  vk_Space: ștergeți calea navei de luptă
   începe
    cu Form1.Image1.Canvas do
    începe
     Brush.Color: = ClWhite;
     Perie.Stil: = bsSolid;
     Fillrect (Form1.Image1.ClientRect);
    Sfârșit;
   Sfârșit;
  vk_Right: cx: = cx + 1;
  vk_Left: cx: = cx-1;
  vk_Up: cy: = cy-1;
  vk_Down: cy: = cy + 1;
 Sfârșit; caz
 Dacă cx < 2 then cx := Form1.Image1.ClientWidth-2;
 Dacă cx> Form1.Image1.ClientWidth -2 atunci cx: = 2;
 Dacă cy < 2 then cy := Form1.Image1.ClientHeight -2 ;
 Dacă cy> Form1.Image1.ClientHeight-2, atunci cy: = 2;
 cu Form1.Image1.Canvas do
 începe
  Pen.Color: = clRed;
  Brush.Color: = ClYellow;
  TextOut (0,0, Format ('% d,% d', [cx, cy]));
  Dreptunghi (cx-2, cy-2, cx + 2, cy + 2);
 Sfârșit;
 Rezultat: = 0;
Pentru a împiedica Windows să treacă apăsările de taste la fereastra țintă, Valoarea rezultatului trebuie să fie o valoare diferită de zero.
Sfârșit;

Asta e. Avem acum codul final de procesare a tastaturii.

Rețineți un singur lucru: acest cod nu este în niciun fel restricționat pentru a fi utilizat doar cu TImage.

Funcția KeyboardHookProc servește ca mecanism general KeyPreview & KeyProcess.