Desidero che il mio modulo gestisca i tasti freccia e posso farlo, a condizione che sul modulo non sia presente alcun pulsante. Perchè è questo?Delphi XE e tasto freccia Trapping con OnKeyDown
risposta
I tasti freccia consentono di spostarsi tra i pulsanti di un modulo. Questo è il comportamento standard di Windows. Sebbene tu possa disabilitare questo comportamento standard, dovresti pensarci due volte prima di andare contro lo standard della piattaforma. I tasti freccia sono pensati per la navigazione.
Se si desidera ottenere il massimo in basso su come un tasto stampa trova la sua strada attraverso il ciclo dei messaggi, mi raccomando di leggere A Key's Odyssey. Se si desidera intercettare la pressione del tasto prima che diventi un tasto di navigazione, è necessario farlo in IsKeyMsg
o precedente. Ad esempio, Seamac answer offre una tale possibilità.
Peter Below (autore di quella Key's Odyssey) è un importante ragazzo della comunità Delphi (TeamB) e un grande collaboratore di JVCL. Bell'articolo –
Poiché sono preempiti per occuparsi di impostare l'attenzione sul prossimo WinControl disponibile.
(Sono abbastanza sicuro che se si inserisce una modifica anziché un pulsante si vede la stessa cosa).
Se si desidera gestirli autonomamente, è possibile fornire all'applicazione un evento OnMessage che filtrerà quelli prima che vengano elaborati e li gestisca da soli.
I messaggi chiave vengono elaborati dai controlli stessi che ricevono questi messaggi, ecco perché quando si è su un pulsante il modulo non riceve il messaggio. Quindi normalmente si dovrà sottoclasse questi controlli, ma la VCL è così gentile da chiedere il modulo di genitorialità che cosa fare se la forma è interessato:
type
TForm1 = class(TForm)
..
private
procedure DialogKey(var Msg: TWMKey); message CM_DIALOGKEY;
..
procedure TForm1.DialogKey(var Msg: TWMKey);
begin
if not (Msg.CharCode in [VK_DOWN, VK_UP, VK_RIGHT, VK_LEFT]) then
inherited;
end;
François editing: per rispondere alla OP domanda iniziale, è è necessario chiamare onKeyDown in qualche modo in modo che il suo codice evento funzioni (sentitevi liberi di modificare, era troppo lungo per un commento).
type
TForm1 = class(TForm)
Button1: TButton;
Button2: TButton;
Button3: TButton;
Button4: TButton;
procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
private
{ Private declarations }
procedure DialogKey(var Msg: TWMKey); message CM_DIALOGKEY;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.DialogKey(var Msg: TWMKey);
begin
case Msg.CharCode of
VK_DOWN, VK_UP, VK_RIGHT, VK_LEFT:
if Assigned(onKeyDown) then
onKeyDown(Self, Msg.CharCode, KeyDataToShiftState(Msg.KeyData));
else
inherited
end;
end;
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
case Key of
VK_DOWN: Top := Top + 5;
VK_UP: Top := Top - 5;
VK_LEFT: Left := Left - 5;
VK_RIGHT: Left := Left + 5;
end;
end;
Penso che tu abbia bisogno di un po 'di spiegazioni su cosa sia speciale su 'CM_DIALOGKEY'. Questo è sicuramente il modo perfetto per cambiare comportamento. Sentiti libero di sovrapporsi alla mia risposta e la cancellerò poiché una risposta esauriente con questo codice in battute è ciò che ho fatto. –
@David - Temo che non sarai in grado di cancellare il tuo post :). Non c'è molto che possa spiegare su CM_DIALOGKEY, è un messaggio composto VCL usato per trasmettere messaggi chiave. Questo è ciò che il mio file di aiuto dice a riguardo: * "Questo è costante Controls.CM_DIALOGKEY" * :). Aggiornamento: La [documentazione] (http://docwiki.embarcadero.com/VCL/2010/en/Controls.CM_DIALOGKEY) è stata migliorata: * "CM_DIALOGKEY rappresenta un messaggio di controllo ed è utilizzato internamente dal framework VCL." * –
Hmm, ho pensato che suonasse come se fosse collegato a 'TApplication.IsDlgMsg'. Infatti, 'TApplication.IsDlgMsg' è rilevante anche qui o il VCL gestisce questi tasti di navigazione piuttosto che le finestre di dialogo di Windows? –
Solo l'oggetto che ha il focus può ricevere un evento di tastiera.
Per consentire al modulo di accedere agli eventi dei tasti di direzione, dichiarare un MsgHandler
nella parte pubblica del modulo. Nel modulo create constructor, assegnare Application.OnMessage
a questo MsgHandler.
Il codice seguente intercetta i tasti freccia solo se provengono da un discendente TButton. Più controlli possono essere aggiunti secondo necessità.
procedure TForm1.FormCreate(Sender: TObject);
begin
Application.OnMessage := Self.MsgHandler;
end;
procedure TForm1.MsgHandler(var Msg: TMsg; var Handled: Boolean);
var
ActiveControl: TWinControl;
key : word;
begin
if (Msg.message = WM_KEYDOWN) then
begin
ActiveControl := Screen.ActiveControl;
// if the active control inherits from TButton, intercept the key.
// add other controls as fit your needs
if not ActiveControl.InheritsFrom(TButton)
then Exit;
key := Msg.wParam;
Handled := true;
case Key of // intercept the wanted keys
VK_DOWN : ; // doStuff
VK_UP : ; // doStuff
VK_LEFT : ; // doStuff
VK_RIGHT : ; // doStuff
else Handled := false;
end;
end;
end;
var
KBHook: HHook; {this intercepts keyboard input}
implementation
{$R *.dfm}
function KeyboardHookProc(Code: Integer; WordParam: Word; LongParam: LongInt): LongInt; stdcall;
begin
case WordParam of
vk_Space: ShowMessage ('space') ;
vk_Right:ShowMessage ('rgt') ;
vk_Left:ShowMessage ('lft') ;
vk_Up: ShowMessage ('up') ;
vk_Down: ShowMessage ('down') ;
end; {case}
end;
procedure TForm4.FormCreate(Sender: TObject);
begin
KBHook:=SetWindowsHookEx(WH_KEYBOARD,@KeyboardHookProc,HInstance,GetCurrentThreadId());
end;
Questo codice funzionerà anche quando un controllo si concentra (pulsanti, caselle di riepilogo), quindi fate attenzione alcuni controlli potrebbero perdere i loro eventi di tastiera (Leggi David haffernans risposta).
eventi della tastiera con controlli mirati
esempio: Se si hanno di testo nella vostra app e Desidero ricevere il testo (se concentrata) anche, quindi
aggiungere un applicationevent1
procedure TForm4.ApplicationEvents1Message(var Msg: tagMSG;var Handled: Boolean);
begin
if Msg.message = WM_KEYFIRST then
KBHook:=SetWindowsHookEx(WH_KEYBOARD,@KeyboardHookProc,HInstance,GetCurrentThreadId());
end;
aggiungere il seguente codice nella parte inferiore dello function KeyboardHookProc
UnhookWindowsHookEx(KBHook);
e rimuovere
KBHook:=SetWindowsHookEx(WH_KEYBOARD,@KeyboardHookProc, HInstance,
GetCurrentThreadId());
dall'evento OnCreate.
- 1. Trapping arrow keys
- 2. Delphi XE: Perso Biblioteca percorso
- 3. SHA1 hashing in Delphi XE
- 4. È possibile utilizzare Indy 10.5.8.0 in Delphi XE e DataSnap?
- 5. Aggiornamento Delphi da RAD Studio a Delphi XE
- 6. Operazione di puntamento non valida - Delphi XE
- 7. Delphi XE: dov'è il mio TValue.Equals()?
- 8. POPCNT in Delphi XE/XE2 64bit
- 9. onKeyDown e onKeyLongPress
- 10. EditText OnKeyDown
- 11. Niente più unità xercesxmldom in Delphi XE?
- 12. Come autogenerare * _TLB.pas in Delphi XE?
- 13. Eventi tasto freccia non in arrivo
- 14. Firefox onKeyDown riconoscono chiave
- 15. Passaggio da Delphi7 a Delphi XE o 2010 per Unicode?
- 16. Perdita di memoria Delphi XE nel metodo TWSDLLookup.Destroy
- 17. Puntatori a tipi generici supportati in Delphi XE?
- 18. TIdHTTP - la sessione è scaduta messaggio in Delphi XE
- 19. Delphi XE - azioni TRibbon inviano sempre attenzione a MainForm
- 20. errore di overflow dello stack quando apro Delphi XE IDE
- 21. Cosa c'è di nuovo nel multithreading in Delphi XE?
- 22. Delphi XE target di build personalizzato è sempre disabilitato
- 23. codici getch e freccia
- 24. Come acquisire un backspace nell'evento onkeydown
- 25. dove e come utilizzare onKey, onkeyDown, onKeyErrore evento in Android?
- 26. Trapping getopt opzioni non valide
- 27. Traccia stack "trapping" middleware rack
- 28. Migrazione del server di build da Delphi XE a Delphi XE2
- 29. Javascript: addEventListener con onkeydown non sembra funzionare
- 30. Rilevazione tasto freccia premere IE tramite javascript/jQuery
Ottima domanda. Scavare nella complessità sottostante di cose come questa è ciò che separa gli esperti dai turisti. Continuate così! –