![]() |
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. |
AW: Shift + NumPadX erkennen
Ich habe das selbe Problem mit Redeemers Vorschlag, weder per TApplicationEvents noch per TApplication, jeweils das TShortcutEvent Event, kommt dabei nur etwas positives heraus wenn numlock ausgeschaltet ist.
Ich hatte gehofft auf diese Weise beides abfangen zu können
Delphi-Quellcode:
Pustekuchen.
procedure TForm1.ApplicationEvents1ShortCut(var Msg: TWMKey;
var Handled: Boolean); var ss: TShiftState; begin ss := KeyDataToShiftState(Msg.KeyData); if ss = [ssShift] then begin if ((Msg.Charcode = VK_NUMPAD0) or (Msg.Charcode = VK_INSERT)) then // theoretisch sollte das ohne/mit numlock codes abdecken begin ShowMessage(IntToStr(Msg.CharCode)); Handled := True; end; end; end; |
AW: Shift + NumPadX erkennen
Hier ein work-around, aber happert noch hier und da, aber um Dir meinen Grundgedanken zu verdeutlichen:
Delphi-Quellcode:
Das Problem: sobald man Shift drückt wechselt NumLock An/Aus/An/Aus usw usf, also da muss noch dolle was gemacht werden, ansonsten klappt es damit ganz gut.
procedure TForm1.ApplicationEvents1ShortCut(var Msg: TWMKey;
var Handled: Boolean); procedure SetNumLock(Active: Boolean); var State: SHORT; Scan: UINT; begin Scan := MapVirtualKey(VK_NUMLOCK, 0); State := GetKeyState(VK_NUMLOCK); // Prüfen ob Status nicht schon korrekt ist if Active xor (State and $0001 = $0001) then begin // User hat den Finger drauf :o) ( also erstmal wieder loslassen ) if State < 0 then keybd_event(VK_NUMLOCK, Scan, KEYEVENTF_KEYUP, 0); // Taste drücken keybd_event(VK_NUMLOCK, Scan, 0, 0); // User hat nicht den Finger drauf :o) ( also loslassen ) if State >= 0 then keybd_event(VK_NUMLOCK, Scan, KEYEVENTF_KEYUP, 0); end; end; var ss: TShiftState; OrgState, KBstate: TKeyboardState; begin ss := KeyDataToShiftState(Msg.KeyData); GetKeyboardState(KBstate); OrgState := KBstate; if ss = [ssShift] then begin if KBstate[VK_NUMLOCK] <> 0 then begin KBstate[VK_NUMLOCK] := 0; SetNumLock(False); SetKeyboardState(KBstate); Msg.CharCode := $0; Handled := True; end; if ((Msg.Charcode = VK_NUMPAD0) or (Msg.Charcode = VK_INSERT)) then begin ShowMessage('Numpad 0 + Shift: '+IntToStr(Msg.CharCode)); Handled := True; end; { if OrgState[VK_NUMLOCK] <> 0 then begin SetKeyboardState(OrgState); SetNumLock(True); Msg.CharCode := $0; end;} if not Handled = True then if (Msg.Charcode <> VK_SHIFT) then ShowMessage(IntToStr(Msg.CharCode)); end; end; |
AW: Shift + NumPadX erkennen
Zitat:
eigentlich habe ich nicht wirklich ein Problem, denn ich habe ja eine funktionierende Lösung, die ich in #1 gezeigt habe. Mein Ansinnen war, eine elegantere Methode aufgezeigt zu bekommen. |
AW: Shift + NumPadX erkennen
Liste der Anhänge anzeigen (Anzahl: 1)
Schau mal bitte in das Projekt rein, ich habe total normale Delphi Methoden veranschaulicht und auch ein SHIFT+NumPadX lässt sich damit auslesen, egal ob NumLock on/off.
|
AW: Shift + NumPadX erkennen
Zitat:
Das folgende wird mir angezeigt: Angegeben habe ich jeweils in der ersten Zeile, die Taste die ich drücke (oder loslasse) und in der zweiten Zeile die 4 Werte die angezeigt werden. NumPad2 Down 2 98 Leer 50 NumPad2 Up 2 98 98 50 Shift Down 2 16 98 50 NumPad1 Down 2 35 16 50 NumPad1 Up 2 16 35 50 Shift Up 2 16 16 50 Bei NumPad1 Down kommt im FormKeyDown genau das, was Probleme macht, nämlich die Information Key=35 und Shift-Taste gedrückt. Also Shift + VK_End, Tatsächlich gedrückt war aber Shift + Numpad1. Sehr schön ist auch zu sehen, das Shift + Numpad1 kein FormKeyPress auslöst. Um auf die Tasten bzw. Tastenkombinationen zu reagieren bleibt also nur FormKeyDown (oder FormKeyUp) - ich bevorzuge FormShortcut. Und da kommt bei Shift + NumpadX etwas anderes als tatsächlich gedrückt wurde. Was ich jetzt nicht so richtig verstehe ist Dein Kommentar "und auch ein SHIFT+NumPadX lässt sich damit auslesen", denn genau das ist nicht der Fall - jedenfalls nicht bei mir. |
AW: Shift + NumPadX erkennen
Welch eine Schande, ich dachte echt das ich per KeyUp und KeyDown schon ganz gut liege.
Ich habe es nicht tief genug mit anderen Tasten getestet bzw total außer Acht gelassen. Tut mir leid für Störung. Ps: Da stehen oftmals noch alte Werte in den Feldern, das war halt ein Schuss in den Ofen auch wenn ich das noch ausbügel mit den Feldern bleibt es falsch. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:23 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