Einzelnen Beitrag anzeigen

Amateurprofi
Online

Registriert seit: 17. Nov 2005
Ort: Hamburg
1.063 Beiträge
 
Delphi XE2 Professional
 
#1

Shift + NumPadX erkennen

  Alt 31. Jul 2018, 18:07
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}
Gruß, Klaus
Die Titanic wurde von Profis gebaut,
die Arche Noah von einem Amateur.
... Und dieser Beitrag vom Amateurprofi....
  Mit Zitat antworten Zitat