![]() |
Shift + NumPadX erkennen
Ich möchte (in FormShortcut) auf alle Tasten, die irgendein Zeichen repräsentieren, reagieren und irgendwelche Aktionen auslösen.
Ich möchte auch unterscheiden können, ob gleichzeitig die Shift-Taste gedrückt ist, oder nicht. Bei den Tasten des Ziffernblocks macht das Probleme weil zum Beispiel bei Shift+NumPad1 nicht etwa NumPad1 als gedrückt gemeldet wird, sondern VK_End. Mein Ausweg für Helden ist, mit GetKeyboardState den Status aller Tasten zu holen und auszuwerten. Zu meiner Überraschung liefert GetKeyboardState teils Informationen die (meine Meinung) nicht viel mit der Realität (oder mit dem, was ich für Realität halte) zu tun hat. Um herauszufinden, was GetKeyboardState liefert habe ich TKeyBoardState in Form einer Matrix ausgegeben, zunächst wenn Shift+NumPad1 gedrückt ist und dann, wenn End gedrückt ist und fand für folgende VK_XX die folgenden Werte. Die Ergebnisse: In beiden Fällen ist TKeyBoardState[VK_End] = $81, als gedrückt. Unterschiedlich waren: VK_LButton ( 1 bei Shift+1, 0 bei End) VK_RButton ( 0 bei Shift+1, 1 bei End) VK_Menu ( 1 bei Shift+1, 0 bei End) VK_RMENU ( 0 bei Shift+1, 1 bei End) Meine Lösung (für Shift+NumPad1) ist, dann wenn VK_End gedrückt ist, ist in TKeyBoardState zu prüfen ob bei VK_LBUTTON eine 1 steht oder nicht. Ist da eine 1 dann interpretiere ich das so, dass Shift+NumPad1 gedrückt sind. Analog mache ich das für NumPad2 bis 6 (andere Numpad-Tasten brauche ich nicht). Das funktioniert, aber ich weiß nicht warum und ich weiß auch nicht, ob das nur bei mir so ist. Nach langer Darstellung was ich mache die Frage: Weiß jemand eine elegantere Lösung?
Code:
TKeyBoardState, wenn Shift + Numpad1 gedrückt sind.
Shift-1 End
01 1 VK_LBUTTON 1 0 02 2 VK_RBUTTON 0 1 08 8 VK_BACK 1 1 09 9 VK_TAB 1 1 0D 13 VK_RETURN 1 1 10 16 VK_SHIFT 1 1 12 18 VK_MENU 1 0 23 35 VK_END 81 81 24 36 VK_HOME 1 1 5B 91 VK_LWIN 1 1 5C 92 VK_RWIN 1 1 90 144 VK_NUMLOCK 1 1 A0 160 VK_LSHIFT 1 1 A2 162 VK_LCONTROL 1 1 A3 163 VK_RCONTROL 1 1 A4 164 VK_LMENU 1 1 A5 165 VK_RMENU 0 1 F0 240 1 1 F3 243 1 1 F6 246 1 1 FB 251 VK_ZOOM 1 1
Code:
0 1 2 3 4 5 6 7 8 9 A B C D E F
-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 00 00 01 00 00 00 00 00 00 01 01 00 00 00 01 00 00 10 01 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 20 00 00 00 81 01 00 00 00 00 00 00 00 00 00 00 00 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 50 00 00 00 00 00 00 00 00 00 00 00 01 01 00 00 00 60 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 A0 01 00 01 01 01 00 00 00 00 00 00 00 00 00 00 00 B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 F0 01 00 00 01 00 00 01 00 00 00 00 01 00 00 00 00
Delphi-Quellcode:
procedure TMain.FormShortCut(var Msg: TWMKey; var Handled: Boolean);
var Key:Word; Shift:TShiftState; //------------------------------------------------------------------------------ FUNCTION GetKeyCode:Boolean; begin Key:=Msg.CharCode; if Key in [VK_Shift,VK_Control,VK_Menu] then Exit(False); // Nur Shift, Ctrl, Alt Shift:=[ssShift,ssCtrl,ssAlt]*KeyDataToShiftState(Msg.KeyData); Result:=True; end; //------------------------------------------------------------------------------ FUNCTION HandlePianoKey:Boolean; var Index:Integer; Tone:Byte; KeyState:TKeyBoardState; begin Result:=(ActiveControl<>reEditor) and (Shift*[ssCtrl,ssAlt]=[]) and (Key<=$FF); if Result then begin if Key in [VK_End,VK_Down,VK_Next,VK_Left,VK_Clear,VK_Right] then begin GetKeyboardState(KeyState); if KeyState[VK_LButton]=1 then begin case Key of VK_End : Key:=VK_NumPad1; VK_Down : Key:=VK_NumPad2; VK_Next : Key:=VK_NumPad3; VK_Left : Key:=VK_NumPad4; VK_Clear : Key:=VK_NumPad5; VK_Right : Key:=VK_NumPad6; else Exit(False); end; Shift:=[ssShift]; end; end; Index:=KeyToToneIndex[Key]; if Index<Length(KeyToTone) then with KeyToTone[Index] do begin if Shift=[] then Tone:=Tone1 else Tone:=Tone2; PianoPlayTone(Tone); Exit; end; end; Result:=False; end; //------------------------------------------------------------------------------ //PROCEDURE StoreKeyStates; //var I:Integer; KeyState:TKeyBoardState; S:String; //begin // GetKeyboardState(KeyState); // S:=' 0 1 2 3 4 5 6 7 8 9 A B C D E F'#13#10+ // ' -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --'#13#10; // for I:=0 to High(KeyState) do begin // if I and 15=0 then S:=S+IntToHex(I and $F0,2)+' '; // S:=S+IntToHex(KeyState[I],2)+' '; // if I and 15=15 then S:=S+#13#10; // end; // ClipBoard.AsText:=S; //end; //------------------------------------------------------------------------------ begin {FormShortCut} Handled:=GetKeyCode; if not Handled then Exit; // war nur Shift, Ctrl, Alt // StoreKeyStates; ... ... if HandlePianoKey then Exit; Handled:=False; end; {FormShortCut} |
AW: Shift + NumPadX erkennen
Frage, was hast Du vor?
Um auf Tastendrücke zu reagieren setze ich KeyPreview des Forms auf True und fülle OnKeyUp mit Leben. Da kann man Key (Word) (also z. B. die $81) und Shift (TShiftState) abfragen. Man bekommt beides als Parameter in die Ereignisroutine geliefert.
Delphi-Quellcode:
Man kann dann in Shift abfragen, ob Strg, Alt oder Shift oder auch 'ne beliebige Kombination daraus betätigt wurde, in Key steht der nummerische Wert der Taste. Kann man dann mit VK_wieauchimmer vergleichen ...
procedure TForm.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
Wäre das 'ne Alternative oder hast Du weiterreichende Anforderungen, die in dem Ereignis nicht umzusetzen sind? |
AW: Shift + NumPadX erkennen
Hallo,
kennt Du das hier schon? Das geht doch in Deine Richtung. ![]() |
AW: Shift + NumPadX erkennen
Zitat:
Ich schriebs explizit: Auf z.B. NumPad1 reagieren und unterscheiden können, ob die Shift-Taste gleichzeitig gedrückt ist. Und genau das funktioniert nicht mit FormKeyUp. Wenn du NumPad1 drückst, wird im FormKeyUp korrekt als Key $61 geliefert und not (ssShift in Shift). Aber wenn du Shift+NumPad1 drückst wird im FormKeyUp als Key $23 = 35 = VK_End und ebenfalls not (ssShift in Shift) geliefert. |
AW: Shift + NumPadX erkennen
Zitat:
Drücke ich NUR NumPad1 funktioniert das; klar. Aber drücke ich Shift + Numpad1 wird als Key VK_End geliefert UND Shift NICHT gedrückt. |
AW: Shift + NumPadX erkennen
Wie sah Dein Code mit
Delphi-Quellcode:
aus?
procedure TForm.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
Ps: Kann es sein das Du das eventuell mit Num-Lock Abfrage realisieren musst? |
AW: Shift + NumPadX erkennen
Meine Frage "Frage, was hast Du vor?" zielte daraufhin, welche Aufgabe mit dem Erkennen von den Tastaturdruckkombinationen erreicht werden soll. Das beim Druck von Shift+NumPad1 eben genau diese Kombination festgestellt werden soll, ist schon klar.
Habe mal ein bisserl rumprobiert: Beim Drücken von Strg und/oder Alt plus einer NumPad-Taste bekommt man die entsprechende Info. Ob man dabei Shift betätigt oder nicht, ändert nichts am Ergebnis. Shift ist nie dabei. Wenn man nun aber Numlock ausschaltet, dann erfährt man auch, ob Shift in der Tastenkombination plus einer NumPad-Taste dabei ist. Meine Googlelitis brachte auch nix zum Vorschein, außer: Du bist nicht alleine mit diesem Problem. |
AW: Shift + NumPadX erkennen
Ich weiß ja nicht, was du machst, aber das hier funktioniert problemlos bei mir und das ist auch, wie man TShortcutEvent verwendet:
Delphi-Quellcode:
Wenn man nicht weiß, was eigentlich los ist:
procedure TollesEvent(var Msg: TWMKey; var Handled: Boolean);
var ss: TShiftState; begin ss := KeyDataToShiftState(Msg.KeyData); if ss = [ssShift] then if Msg.Charcode = VK_NUMPAD0 then // =96 TueTolleSachen(); end;
Delphi-Quellcode:
uses Menus;
procedure TollesEvent(var Msg: TWMKey; var Handled: Boolean); var ss: TShiftState; begin ss := KeyDataToShiftState(Msg.KeyData); Caption := IfThen(ssCtrl in ss, 'Strg+') + IfThen(ssShift in ss, 'Umsch+') + IfThen(ssAlt in ss, 'Alt+') + ShortCutToText(Msg.CharCode) + '/' + IntToStr(Msg.CharCode); end; |
AW: Shift + NumPadX erkennen
Zitat:
Delphi-Quellcode:
"Info" ist eine meiner Standard-Prozeduren, die einen Text in dem durch den ersten Parameter definierten Panel der Statusbar ausgibt.
procedure TMain.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin Info(piInfo,IntToHex(Key,2)+' '+IntToStr(Ord(ssShift in Shift))); end; NumLock ist na klar "down". |
AW: Shift + NumPadX erkennen
Zitat:
Hab deinen Code im FormShortCut unverändert eingefügt - und funktioniert nicht (bei Shift + NumPadX) Unter "funktioniert" verstehe ich, um bei deinem erstgenannten Code zu bleiben, dass die Prozedur TueTolleSachen() ausgeführt wird, wenn ich Shift + Numpad1 (bei deinem Beispiel NumPad0) drücke. Falls es dir entgangen ist: So ziemlich genau das, was du vorschlägst mach ich in dem in #1 gezeigten FormShortcut. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:40 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz