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 helpen!
Toetsenbordinvoer onderscheppen
De meeste Delphi-applicaties verwerken doorgaans gebruikersinvoer via specifieke event-handlers, waarmee we gebruikers kunnen vastleggen toetsaanslagen en proces muis beweging.
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.Windows Haken
Technisch gezien is een "hook" -functie een callback-functie die in het Windows-bericht kan worden ingevoegd systeem zodat een toepassing toegang heeft tot de berichtenstroom voordat andere verwerking van het bericht plaatsvindt plaats. Onder veel soorten Windows-haken wordt een toetsenbordhaak genoemd wanneer de toepassing de roept GetMessage () of PeekMessage () functie en er is een WM_KEYUP of WM_KEYDOWN toetsenbordbericht om werkwijze.
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 die hook-functies worden 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 winstwaarde van SetWindowsHookEx is een hendel aan de haak die net is geïnstalleerd. Voordat de toepassing wordt beëindigd, moet de toepassing de UnhookWindowsHookEx functie om systeembronnen vrij te maken die aan de haak zijn gekoppeld.
Voorbeeld van toetsenbordhaak
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. Omdat TImage geen toetsaanslagen kan ontvangen via standaard toetsenbordgebeurtenissen, maken we een haakfunctie die alle toetsenbordinvoer naar ons tekenoppervlak onderschept.
TImage Toetsenbordgebeurtenissen verwerken
Begin 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 wat nodig globale variabelen:
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,
HInstantie
GetCurrentThreadId ());
{plaats het gevechtsschip in het midden van het scherm}
cx: = Image1.ClientWidth div 2;
cy: = Image1.ClientHeight div 2;
Image1.Canvas. PenPos: = Punt (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
Borstel. Kleur: = clWhite;
Borstel. Stijl: = 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 dan cx: = Form1.Image1.ClientWidth-2;
Als cx> Form1.Image1.ClientWidth -2 dan cx: = 2;
Als cy <2 dan cy: = Form1.Image1.ClientHeight -2;
Als cy> Form1.Image1.ClientHeight-2 dan cy: = 2;
met Form1.Image1.Canvas doen
beginnen
Pen. Kleur: = clRed;
Borstel. Kleur: = geel;
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 op geen enkele manier beperkt om alleen met TImage te worden gebruikt.
De functie KeyboardHookProc dient als een algemeen KeyPreview & KeyProcess-mechanisme.