Considera per un momento la creazione di alcuni giochi arcade veloci. Tutta la grafica viene visualizzata, diciamo, in un TPainBox. TPaintBox non è in grado di ricevere lo stato attivo dell'input: nessun evento viene generato quando l'utente preme un tasto; non possiamo intercettare i tasti cursore per muovere la nostra corazzata. Aiuto Delphi!
La maggior parte delle applicazioni Delphi in genere gestiscono l'input dell'utente tramite gestori di eventi specifici, quelli che ci consentono di catturare i tasti utente e di elaborare il movimento del mouse.
Sappiamo che il focus è la capacità di ricevere l'input dell'utente tramite il mouse o la tastiera. Solo il l'oggetto che ha lo stato attivo può ricevere un evento da tastiera. Alcuni controlli, come TImage, TPaintBox, TPanel e TLabel non possono ricevere lo stato attivo. Lo scopo principale della maggior parte dei controlli grafici è visualizzare testo o grafica.
Se vogliamo intercettare l'input da tastiera per i controlli che non possono ricevere lo stato attivo dell'input, dovremo occuparci di API, hook, callback e messaggi di Windows.
Tecnicamente, una funzione "hook" è una funzione di callback che può essere inserita nel sistema di messaggi di Windows in modo che un'applicazione possa accedere al flusso di messaggi prima che abbia luogo un'altra elaborazione del messaggio. Tra molti tipi di hook di Windows, viene chiamato un hook di tastiera ogni volta che l'applicazione chiama la funzione GetMessage () o PeekMessage () e c'è un messaggio da tastiera WM_KEYUP o WM_KEYDOWN da elaborare.
Per creare un hook di tastiera che intercetta tutti gli input da tastiera diretti a un determinato thread, dobbiamo chiamare SetWindowsHookEx Funzione API. Le routine che ricevono gli eventi della tastiera sono funzioni di callback definite dall'applicazione chiamate funzioni hook (KeyboardHookProc). Windows chiama la funzione hook per ciascun messaggio di battitura (tasto su e tasto giù) prima che il messaggio venga inserito nella coda dei messaggi dell'applicazione. La funzione hook può elaborare, modificare o scartare i tasti. Gli hook possono essere locali o globali.
Il valore di ritorno di SetWindowsHookEx è un handle per il gancio appena installato. Prima di terminare, un'applicazione deve chiamare il UnhookWindowsHookEx funzione per liberare risorse di sistema associate all'hook.
Come dimostrazione degli hook della tastiera, creeremo un progetto con controllo grafico in grado di ricevere la pressione dei tasti. TImage è derivato da TGraphicControl, può essere utilizzato come superficie di disegno per il nostro ipotetico gioco di battaglia. Poiché TImage non è in grado di ricevere pressioni da tastiera attraverso eventi da tastiera standard, creeremo una funzione hook che intercetta tutti gli input da tastiera diretti verso la nostra superficie di disegno.
Avviare un nuovo progetto Delphi e posizionare un componente Image in un modulo. Impostare la proprietà Image1.Align su alClient. Questo è tutto per la parte visiva, ora dobbiamo fare un po 'di codice. Innanzitutto, avremo bisogno di alcune variabili globali:
var
Form1: TForm1;
KBHook: HHook; questo intercetta l'input da tastiera
cx, cy: intero; traccia la posizione della nave da battaglia
dichiarazione di richiamata
funzione KeyboardHookProc (Codice: intero; WordParam: Word; LongParam: LongInt): LongInt; stdcall;
implementazione
...
Per installare un hook, chiamiamo SetWindowsHookEx nell'evento OnCreate di un modulo.
procedura TForm1.FormCreate (mittente: TObject);
inizio
Imposta il gancio della tastiera in modo che possiamo intercettare l'input da tastiera
KBHook: = SetWindowsHookEx (WH_KEYBOARD,
callback> @KeyboardHookProc,
hInstance,
GetCurrentThreadId ());
posiziona la nave da battaglia al centro dello schermo
cx: = Image1.ClientWidth div 2;
cy: = Image1.ClientHeight div 2;
Image1.Canvas.PenPos: = Point (cx, cy);
fine;
Per liberare risorse di sistema associate all'hook, dobbiamo chiamare la funzione UnhookWindowsHookEx nell'evento OnDestroy:
procedura TForm1.FormDestroy (mittente: TObject);
inizio
sganciare l'intercettazione da tastiera
UnHookWindowsHookEx (KBHook);
fine;
La parte più importante di questo progetto è la Procedura di richiamata KeyboardHookProc utilizzato per elaborare i tasti.
funzione KeyboardHookProc (Codice: intero; WordParam: Word; LongParam: LongInt): LongInt;
inizio
caso WordParam di
vk_Space: cancella il percorso della nave da battaglia
inizio
con Form1.Image1.Canvas do
inizio
Brush.Color: = clWhite;
Brush.Style: = bsSolid;
Fillrect (Form1.Image1.ClientRect);
fine;
fine;
vk_Right: cx: = cx + 1;
vk_Left: cx: = cx-1;
vk_Up: cy: = cy-1;
vk_Down: cy: = cy + 1;
fine; Astuccio
Se cx < 2 then cx := Form1.Image1.ClientWidth-2;
Se cx> Form1.Image1.ClientWidth -2 quindi cx: = 2;
Se il cy < 2 then cy := Form1.Image1.ClientHeight -2 ;
Se cy> Form1.Image1.ClientHeight-2 quindi cy: = 2;
con Form1.Image1.Canvas do
inizio
Pen.Color: = clRed;
Brush.Color: = clYellow;
TextOut (0,0, formato ('% d,% d', [cx, cy]));
Rettangolo (cx-2, cy-2, cx + 2, cy + 2);
fine;
Risultato: = 0;
Per impedire a Windows di passare le sequenze di tasti alla finestra di destinazione, il valore Risultato deve essere un valore diverso da zero.
fine;
Questo è tutto. Ora abbiamo l'ultimo codice di elaborazione della tastiera.
Nota solo una cosa: questo codice non è in alcun modo limitato per essere utilizzato solo con TImage.
La funzione KeyboardHookProc funge da meccanismo KeyPreview e KeyProcess generale.