Overweeg even om een snel arcade-spel te maken. Alle afbeeldingen worden, laten we zeggen, weergegeven in een TPainBox. TPaintBox kan de invoerfocus niet ontvangen - er worden geen gebeurtenissen geactiveerd wanneer de gebruiker op een toets drukt; we kunnen cursortoetsen niet onderscheppen om ons slagschip te verplaatsen. Delphi help!
De meeste Delphi-applicaties verwerken doorgaans gebruikersinvoer via specifieke eventhandlers, waarmee we gebruikersaanslagen kunnen vastleggen en muisbewegingen kunnen verwerken.
We weten dat focus de mogelijkheid is om gebruikersinvoer te ontvangen via de muis of het toetsenbord. Alleen de object dat de focus heeft, kan een toetsenbordgebeurtenis ontvangen. Sommige bedieningselementen, zoals TImage, TPaintBox, TPanel en TLabel kunnen geen focus krijgen. Het primaire doel van de meeste grafische bedieningselementen is om tekst of afbeeldingen weer te geven.
Als we toetsenbordinvoer willen onderscheppen voor besturingselementen die de invoerfocus niet kunnen ontvangen, hebben we te maken met Windows API, hooks, callbacks en berichten.
Technisch gezien is een "hook" -functie een callback-functie die kan worden ingevoegd in het Windows-berichtensysteem, zodat een toepassing toegang heeft tot de berichtenstroom voordat andere verwerking van het bericht plaatsvindt. Onder veel soorten Windows-haken wordt een toetsenbordhaak aangeroepen wanneer de toepassing de functie GetMessage () of PeekMessage () aanroept en er een WM_KEYUP- of WM_KEYDOWN-toetsenbordbericht moet worden verwerkt.
Om een toetsenbordhaak te maken die alle toetsenbordinvoer onderschept die naar een bepaalde thread is gericht, moeten we bellen SetWindowsHookEx API-functie. De routines die de toetsenbordgebeurtenissen ontvangen, zijn door de toepassing gedefinieerde callback-functies, hook-functies genoemd (KeyboardHookProc). Windows roept uw hook-functie aan voor elk toetsaanslagbericht (toets omhoog en toets omlaag) voordat het bericht in de berichtenwachtrij van de toepassing wordt geplaatst. De hook-functie kan toetsaanslagen verwerken, wijzigen of weggooien. Haken kunnen lokaal of wereldwijd zijn.
De geretourneerde waarde van SetWindowsHookEx is een greep naar de net geïnstalleerde haak. Voordat de toepassing wordt beëindigd, moet de toepassing de UnhookWindowsHookEx functie om systeembronnen vrij te maken die aan de haak zijn gekoppeld.
Als een demonstratie van toetsenbordhaken maken we een project met grafische besturing dat toetsaanslagen kan ontvangen. TImage is afgeleid van TGraphicControl en kan worden gebruikt als een tekenoppervlak voor ons hypothetische vechtspel. Aangezien TImage geen toetsaanslagen kan ontvangen via standaard toetsenbordgebeurtenissen, maken we een haakfunctie die alle toetsenbordinvoer onderschept die naar ons tekenoppervlak is gericht.
Start een nieuw Delphi-project en plaats een afbeeldingscomponent op een formulier. Stel Image1.Align property in op alClient. Dat is het voor het visuele gedeelte, nu moeten we wat codering doen. Eerst hebben we enkele globale variabelen nodig:
var
Form1: TForm1;
KBHook: HHook; dit onderschept toetsenbordinvoer
cx, cy: geheel getal; volg positie gevechtsschip
terugbelverklaring
functie KeyboardHookProc (Code: Integer; WordParam: Word; LongParam: LongInt): LongInt; stdcall;
implementatie
...
Om een hook te installeren, roepen we SetWindowsHookEx aan in de OnCreate-gebeurtenis van een formulier.
procedure TForm1.FormCreate (afzender: TObject);
beginnen
Stel de toetsenbordhaak in zodat we toetsenbordinvoer kunnen onderscheppen
KBHook: = SetWindowsHookEx (WH KEYBOARD,
callback> @KeyboardHookProc,
hInstance,
GetCurrentThreadId ());
plaats het gevechtsschip in het midden van het scherm
cx: = Image1.ClientWidth div 2;
cy: = Image1.ClientHeight div 2;
Image1.Canvas.PenPos: = Point (cx, cy);
einde;
Om systeembronnen vrij te maken die aan de hook zijn gekoppeld, moeten we de functie UnhookWindowsHookEx aanroepen in de OnDestroy-gebeurtenis:
procedure TForm1.FormDestroy (afzender: TObject);
beginnen
haak de onderschepping van het toetsenbord los
UnHookWindowsHookEx (KBHook);
einde;
Het belangrijkste onderdeel van dit project is het KeyboardHookProc callback-procedure gebruikt om toetsaanslagen te verwerken.
functie KeyboardHookProc (Code: Integer; WordParam: Word; LongParam: LongInt): LongInt;
beginnen
case WordParam van
vk_Space: pad van gevechtsschip wissen
beginnen
met Form1.Image1.Canvas doen
beginnen
Brush.Color: = clWhite;
Brush.Style: = bsSolid;
Fillrect (Form1.Image1.ClientRect);
einde;
einde;
vk_Right: cx: = cx + 1;
vk_Left: cx: = cx-1;
vk_Up: cy: = cy-1;
vk_Down: cy: = cy + 1;
einde; geval
Als cx < 2 then cx := Form1.Image1.ClientWidth-2;
Als cx> Form1.Image1.ClientWidth -2 dan cx: = 2;
Als cy < 2 then cy := Form1.Image1.ClientHeight -2 ;
Als cy> Form1.Image1.ClientHeight-2 dan cy: = 2;
met Form1.Image1.Canvas doen
beginnen
Pen.Color: = clRed;
Brush.Color: = clGeel;
TextOut (0,0, Format ('% d,% d', [cx, cy]));
Rechthoek (cx-2, cy-2, cx + 2, cy + 2);
einde;
Resultaat: = 0;
Om te voorkomen dat Windows de toetsaanslagen doorgeeft aan het doelvenster, moet de resultaatwaarde een waarde van nul zijn.
einde;
Dat is het. We hebben nu de ultieme toetsenbordverwerkingscode.
Let op slechts één ding: deze code is geenszins beperkt om alleen met TImage te worden gebruikt.
De functie KeyboardHookProc dient als een algemeen KeyPreview & KeyProcess-mechanisme.