Abfangen von Tastatureingaben mit Delphi

Betrachten Sie für einen Moment die Erstellung eines schnellen Arcade-Spiels. Alle Grafiken werden beispielsweise in einer TPainBox angezeigt. TPaintBox kann den Eingabefokus nicht empfangen. Es werden keine Ereignisse ausgelöst, wenn der Benutzer eine Taste drückt. Wir können keine Cursortasten abfangen, um unser Schlachtschiff zu bewegen. Delphi-Hilfe!

Tastatureingabe abfangen

Die meisten Delphi-Anwendungen verarbeiten Benutzereingaben in der Regel über bestimmte Ereignishandler, die es uns ermöglichen, Benutzertastenanschläge zu erfassen und Mausbewegungen zu verarbeiten.

Wir wissen, dass Fokus die Fähigkeit ist, Benutzereingaben über die Maus oder die Tastatur zu empfangen. Nur der Objekt, das den Fokus hat, kann ein Tastaturereignis empfangen. Einige Steuerelemente wie TImage, TPaintBox, TPanel und TLabel können den Fokus nicht erhalten. Der Hauptzweck der meisten Grafiksteuerelemente ist die Anzeige von Text oder Grafiken.

Wenn wir Tastatureingaben für Steuerelemente abfangen möchten, die den Eingabefokus nicht erhalten, müssen wir uns mit Windows-API, Hooks, Rückrufen und Nachrichten befassen.

Windows-Haken

Technisch gesehen ist eine "Hook" -Funktion eine Rückruffunktion, die in das Windows-Nachrichtensystem eingefügt werden kann, damit eine Anwendung auf den Nachrichtenstrom zugreifen kann, bevor eine andere Verarbeitung der Nachricht stattfindet. Unter vielen Arten von Windows-Hooks wird ein Tastatur-Hook aufgerufen, wenn die Anwendung die Funktion GetMessage () oder PeekMessage () aufruft und eine WM_KEYUP- oder WM_KEYDOWN-Tastaturnachricht zu verarbeiten ist.

Um einen Tastatur-Hook zu erstellen, der alle Tastatureingaben abfängt, die an einen bestimmten Thread gerichtet sind, müssen wir callen SetWindowsHookEx API-Funktion. Die Routinen, die die Tastaturereignisse empfangen, sind anwendungsdefinierte Rückruffunktionen, die als Hook-Funktionen (KeyboardHookProc) bezeichnet werden. Windows ruft Ihre Hook-Funktion für jede Tastenanschlagsnachricht (Taste hoch und Taste runter) auf, bevor die Nachricht in die Nachrichtenwarteschlange der Anwendung gestellt wird. Die Hook-Funktion kann Tastatureingaben verarbeiten, ändern oder verwerfen. Hooks können lokal oder global sein.

Der Rückgabewert von SetWindowsHookEx ist ein Handle für den gerade installierten Hook. Vor dem Beenden muss eine Anwendung die aufrufen UnhookWindowsHookEx Funktion zum Freigeben von Systemressourcen, die dem Hook zugeordnet sind.

Keyboard Hook Beispiel

Als Demonstration von Tastatur-Hooks erstellen wir ein Projekt mit grafischer Steuerung, das Tastendrücke empfangen kann. TImage ist von TGraphicControl abgeleitet und kann als Zeichenfläche für unser hypothetisches Kampfspiel verwendet werden. Da TImage keine Tastatureingaben über Standardtastaturereignisse empfangen kann, erstellen wir eine Hook-Funktion, die alle Tastatureingaben abfängt, die an unsere Zeichenoberfläche gerichtet sind.

TImage-Verarbeitung von Tastaturereignissen

Starten Sie ein neues Delphi-Projekt und platzieren Sie eine Image-Komponente in einem Formular. Setzen Sie die Image1.Align-Eigenschaft auf alClient. Das ist es für den visuellen Teil, jetzt müssen wir etwas programmieren. Zunächst benötigen wir einige globale Variablen:

 var
  Form1: TForm1;
  KBHook: HHook; dies fängt die Tastatureingabe ab
  cx, cy: ganze Zahl; Position des Schlachtschiffes verfolgen
  Rückruferklärung
  Funktion KeyboardHookProc (Code: Integer; WordParam: Word; LongParam: LongInt): LongInt; stdcall;
Implementierung

Um einen Hook zu installieren, rufen wir SetWindowsHookEx im OnCreate-Ereignis eines Formulars auf.

 procedure TForm1.FormCreate (Sender: TObject);
Start
 Stellen Sie den Tastaturhaken so ein, dass wir Tastatureingaben abfangen können
 KBHook: = SetWindowsHookEx (WH_KEYBOARD,
           Rückruf> @KeyboardHookProc,
                          HInstanz,
                          GetCurrentThreadId ());
 Platziere das Schlachtschiff in der Mitte des Bildschirms
 cx: = Image1.ClientWidth div 2;
 cy: = Image1.ClientHeight div 2;
 Image1.Canvas.PenPos: = Point (cx, cy);
Ende;

Um dem Hook zugeordnete Systemressourcen freizugeben, müssen wir die UnhookWindowsHookEx-Funktion im OnDestroy-Ereignis aufrufen:

 procedure TForm1.FormDestroy (Sender: TObject);
Start
  Tastatur abfangen
  UnHookWindowsHookEx (KBHook);
Ende;

Der wichtigste Teil dieses Projekts ist der KeyboardHookProc-Rückrufprozedur wird zum Verarbeiten von Tastenanschlägen verwendet.

 Funktion KeyboardHookProc (Code: Integer; WordParam: Word; LongParam: LongInt): LongInt;
Start
 Fall WordParam von
  vk_Space: Kampfschiffspfad löschen
   Start
    mit Form1.Image1.Canvas tun
    Start
     Brush.Color: = clWhite;
     Brush.Style: = bsSolid;
     Fillrect (Form1.Image1.ClientRect);
    Ende;
   Ende;
  vk_Right: cx: = cx + 1;
  vk_Left: cx: = cx-1;
  vk_Up: cy: = cy-1;
  vk_Down: cy: = cy + 1;
 Ende; Fall
 Wenn cx < 2 then cx := Form1.Image1.ClientWidth-2;
 Wenn cx> Form1.Image1.ClientWidth -2, dann ist cx: = 2;
 Wenn cy < 2 then cy := Form1.Image1.ClientHeight -2 ;
 Wenn cy> Form1.Image1.ClientHeight-2, dann cy: = 2;
 mit Form1.Image1.Canvas tun
 Start
  Pen.Color: = clRed;
  Brush.Color: = clYellow;
  TextOut (0,0, Format ('% d,% d', [cx, cy]));
  Rechteck (cx-2, cy-2, cx + 2, cy + 2);
 Ende;
 Ergebnis: = 0;
Um zu verhindern, dass Windows die Tastenanschläge an das Zielfenster weiterleitet, muss der Ergebniswert ein Wert ungleich Null sein.
Ende;

Das ist es. Wir haben jetzt den ultimativen Tastaturverarbeitungscode.

Beachten Sie nur eines: Dieser Code darf in keiner Weise nur mit TImage verwendet werden.

Die KeyboardHookProc-Funktion dient als allgemeiner KeyPreview- und KeyProcess-Mechanismus.