Avlyssna tangentbordinmatning med Delphi

Tänk ett ögonblick på att skapa ett snabbt arkadspel. All grafik visas, låt oss säga, i en TPainBox. TPaintBox kan inte ta emot inmatningsfokus - inga händelser avfyras när användaren trycker på en knapp; vi kan inte fånga markörtangenterna för att flytta vårt slagskepp. Delphi hjälp!

Avlyssna tangentbordets ingång

De flesta Delphi-applikationer hanterar vanligtvis användarinmatning genom specifika händelseshanterare, de som gör att vi kan fånga användare tangenttryckningar och process musrörelse.

Vi vet att fokus är förmågan att ta emot användarinmatning via musen eller tangentbordet. Bara objekt som har fokus kan ta emot en tangentbordshändelse. Vissa kontroller, som TImage, TPaintBox, TPanel och TLabel kan inte få fokus. Det huvudsakliga syftet med de flesta grafiska kontroller är att visa text eller grafik.

Om vi ​​vill avlyssna tangentbordsinmatningen för kontroller som inte kan få inmatningsfokus måste vi ta itu med Windows API, krokar, återuppringningar och meddelanden.

Windows krokar

instagram viewer

Tekniskt sett är en "hook" -funktion en återuppringningsfunktion som kan infogas i Windows-meddelandet system så att en applikation kan komma åt meddelandeströmmen innan annan behandling av meddelandet tar plats. Bland många typer av fönsterkrokar kallas en tangentbordskrok när applikationen anropar GetMessage () eller PeekMessage () -funktionen och det finns ett WM_KEYUP- eller WM_KEYDOWN-tangentbordmeddelande till bearbeta.

För att skapa en tangentbordskrok som fångar upp alla tangentbordsinmatningar riktade till en given tråd måste vi ringa SetWindowsHookEx API-funktion. Rutinerna som tar emot tangentbordshändelserna är applikationsdefinerade återuppringningsfunktioner som kallas hook-funktioner (KeyboardHookProc). Windows anropar din krokfunktion för varje tangenttryckningsmeddelande (tangent upp och ner) innan meddelandet placeras i programmets meddelandekö. Krokfunktionen kan bearbeta, ändra eller kasta tangenttryckningar. Krokar kan vara lokala eller globala.

De returvärde av SetWindowsHookEx är ett handtag på kroken som just har installerats. Innan en ansökan avslutas måste en ansökan ringa UnhookWindowsHookEx funktion för att frigöra systemresurser kopplade till kroken.

Exempel på tangentbordskrok

Som en demonstration av tangentbordskrokar skapar vi ett projekt med grafisk kontroll som kan ta emot knapptryckningar. TImage härrör från TGraphicControl, det kan användas som en teckningsyta för vårt hypotetiska stridsspel. Eftersom TImage inte kan ta emot tangentbordspress genom standard tangentbordshändelser skapar vi en krokfunktion som avbryter all tangentbordingång riktad till vår ritningsyta.

TImage Bearbetar tangentbordshändelser

Börja om Delphi-projektet och placera en bildkomponent på ett formulär. Ställ in Image1.Align egenskapen till alClient. Det är det för den visuella delen, nu måste vi göra lite kodning. Först behöver vi lite globala variabler:

 var
Form1: TForm1;
KBHook: HHook; {detta avlyssnar tangentbordsinmatning}
cx, cy: heltal; {spåra stridsfartygets position}
{återuppringningsdeklaration}
funktion KeyboardHookProc (kod: heltal; WordParam: Word; LongParam: LongInt): LongInt; stdcall;
genomförande
...

För att installera en krok, kallar vi SetWindowsHookEx i händelsen OnCreate på ett formulär.

 procedur TForm1.FormCreate (avsändare: TObject);
Börja
{Ställ in tangentbordskroken så att vi kan fånga in tangentbordet}
KBHook: = SetWindowsHookEx (WH_KEYBOARD,
{callback>} @KeyboardHookProc,
HInstance,
GetCurrentThreadId ());
{placera stridsfartyget mitt på skärmen}
cx: = Bild1.ClientWidth div 2;
cy: = Image1.ClientHeight div 2;
Image1.Canvas. PenPos: = Punkt (cx, cy);
slutet;

För att frigöra systemresurser kopplade till kroken måste vi anropa funktionen UnhookWindowsHookEx i händelsen OnDestroy:

 procedur TForm1.FormDestroy (avsändare: TObject);
Börja
{ta bort tangentbordets avlyssning}
UnHookWindowsHookEx (KBHook);
slutet;

Den viktigaste delen av detta projekt är KeyboardHookProc återuppringningsprocedur används för att behandla tangenttryckningar.

 funktion KeyboardHookProc (kod: heltal; WordParam: Word; LongParam: LongInt): LongInt;
Börja
fall WordParam av
vk_Space: {radera stridsfartygets väg}
Börja
med Form1.Image1.Canvas do
Börja
Borsta. Färg: = clWhite;
Borsta. Stil: = bsSolid;
Fillrect (Form1.Image1.ClientRect);
slutet;
slutet;
vk_Right: cx: = cx + 1;
vk_Left: cx: = cx-1;
vk_Up: cy: = cy-1;
vk_Down: cy: = cy + 1;
slutet; {fall}
Om cx <2, då cx: = Form1.Image1.ClientWidth-2;
Om cx> Form1.Image1.ClientWidth -2, då cx: = 2;
Om cy <2 då cy: = Form1.Image1.ClientHeight -2;
Om cy> Form1.Image1.ClientHeight-2 då cy: = 2;
med Form1.Image1.Canvas do
Börja
Penna. Färg: = clRed;
Borsta. Färg: = clYellow;
TextOut (0,0, Format ('% d,% d', [cx, cy]));
Rektangel (cx-2, cy-2, cx + 2, cy + 2);
slutet;
Resultera: = 0;
{För att förhindra Windows från att skicka tangenttryckningarna till målfönstret måste resultatvärdet vara ett icke-nollvärde.}
slutet;

Det är allt. Vi har nu den ultimata koden för bearbetning av tangentbord.

Observera bara en sak: den här koden är inte begränsad till att endast användas med TImage.

Funktionen KeyboardHookProc fungerar som en generell KeyPreview & KeyProcess-mekanism.