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!
De flesta Delphi-applikationer hanterar vanligtvis användarinmatning genom specifika händelseshanterare, de som gör det möjligt för oss att fånga användarnas knapptryckningar och bearbeta musrörelser.
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.
Tekniskt sett är en "hook" -funktion en återuppringningsfunktion som kan infogas i Windows-meddelandesystemet så att en applikation kan komma åt meddelandeströmmen innan annan behandling av meddelandet äger rum. Bland många typer av fönsterkrokar kallas en tangentbordskrok när applikationen kallar GetMessage () eller PeekMessage () -funktionen och det finns ett WM_KEYUP- eller WM_KEYDOWN-tangentbord för att 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.
Returvärdet för SetWindowsHookEx är ett handtag till 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.
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.
Starta nytt Delphi-projekt 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 några 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
Brush.Color: = clWhite;
Brush.Style: = 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 then cx := Form1.Image1.ClientWidth-2;
Om cx> Form1.Image1.ClientWidth -2, då cx: = 2;
Om cy < 2 then cy := Form1.Image1.ClientHeight -2 ;
Om cy> Form1.Image1.ClientHeight-2 då cy: = 2;
med Form1.Image1.Canvas do
Börja
Pen.Färg: = clRed;
Brush.Color: = clellow;
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 att Windows överför 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 användas endast med TImage.
Funktionen KeyboardHookProc fungerar som en generell KeyPreview & KeyProcess-mekanism.