Nieuwe

Toetsenbordinvoer onderscheppen met Delphi

Toetsenbordinvoer onderscheppen met Delphi

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!

Toetsenbordinvoer onderscheppen

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.

Windows Haken

Technisch gezien is een "hook" -functie een callback-functie die in het Windows-berichtensysteem kan worden ingevoegd, zodat een toepassing toegang heeft tot de berichtenstroom voordat andere verwerking van het bericht plaatsvindt. Onder vele typen 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 (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 haakfunctie kan toetsaanslagen verwerken, wijzigen of weggooien. Haken kunnen lokaal of wereldwijd zijn.

De geretourneerde waarde van SetWindowsHookEx is een greep naar de haak die zojuist is geïnstalleerd. Voordat een 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

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 een aantal 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 (Sender: 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 (Sender: 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  geval WordParam van vk_Space: {pad van gevechtsschip wissen}    beginnen     met Form1.Image1.Canvas do     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 vervolgens cx: = Form1.Image1.ClientWidth-2;Als cx> Form1.Image1.ClientWidth -2 vervolgens cx: = 2;Als cy <2 vervolgens cy: = Form1.Image1.ClientHeight -2;Als cy> Form1.Image1.ClientHeight-2 vervolgens cy: = 2;met Form1.Image1.Canvas do  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.