Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Shift + NumPadX erkennen (https://www.delphipraxis.net/197339-shift-numpadx-erkennen.html)

Amateurprofi 31. Jul 2018 17:07

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:
             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
TKeyBoardState, wenn Shift + Numpad1 gedrückt sind.

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}

Delphi.Narium 31. Jul 2018 17:39

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:
procedure TForm.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
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 ...

Wäre das 'ne Alternative oder hast Du weiterreichende Anforderungen, die in dem Ereignis nicht umzusetzen sind?

hoika 31. Jul 2018 18:23

AW: Shift + NumPadX erkennen
 
Hallo,
kennt Du das hier schon?
Das geht doch in Deine Richtung.

https://social.msdn.microsoft.com/Fo...rum=vblanguage

Amateurprofi 31. Jul 2018 18:42

AW: Shift + NumPadX erkennen
 
Zitat:

Zitat von Delphi.Narium (Beitrag 1409245)
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:
procedure TForm.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
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 ...

Wäre das 'ne Alternative oder hast Du weiterreichende Anforderungen, die in dem Ereignis nicht umzusetzen sind?

Was ich wollte?:
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.

Amateurprofi 31. Jul 2018 18:50

AW: Shift + NumPadX erkennen
 
Zitat:

Zitat von hoika (Beitrag 1409250)
Hallo,
kennt Du das hier schon?
Das geht doch in Deine Richtung.

https://social.msdn.microsoft.com/Fo...rum=vblanguage

Auch das funktioniert nicht.
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.

KodeZwerg 31. Jul 2018 19:16

AW: Shift + NumPadX erkennen
 
Wie sah Dein Code mit
Delphi-Quellcode:
procedure TForm.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
aus?

Ps: Kann es sein das Du das eventuell mit Num-Lock Abfrage realisieren musst?

Delphi.Narium 31. Jul 2018 19:17

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.

Redeemer 31. Jul 2018 19:55

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:
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;
Wenn man nicht weiß, was eigentlich los ist:
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;

Amateurprofi 31. Jul 2018 20:02

AW: Shift + NumPadX erkennen
 
Zitat:

Zitat von KodeZwerg (Beitrag 1409253)
Wie sah Dein Code mit
Delphi-Quellcode:
procedure TForm.FormKeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
aus?

Ps: Kann es sein das Du das eventuell mit Num-Lock Abfrage realisieren musst?

Delphi-Quellcode:
procedure TMain.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
   Info(piInfo,IntToHex(Key,2)+' '+IntToStr(Ord(ssShift in Shift)));
end;
"Info" ist eine meiner Standard-Prozeduren, die einen Text in dem durch den ersten Parameter definierten Panel der Statusbar ausgibt.

NumLock ist na klar "down".

Amateurprofi 31. Jul 2018 20:16

AW: Shift + NumPadX erkennen
 
Zitat:

Zitat von Redeemer (Beitrag 1409259)
Ich weiß ja nicht, was du machst, aber das hier funktioniert problemlos bei mir und das ist auch, wie man TShortcutEvent verwendet:
Delphi-Quellcode:
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;
Wenn man nicht weiß, was eigentlich los ist:
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;

Ich vermute "TollesEvent" ist "FormShortCut"
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.
Seite 1 von 2  1 2      

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