0

I am trying to determine the key that has been pressed in the OnKeyDown of a button (FMX, XE3), but I'm currently finding myself unable to differentiate between numpad keys and regular keys ...

Depending on which key I'm pressing I can either use Key or KeyChar to find out which key has been pressed. For instance, pressing F1 sends 112 and #0 so I can use the VkCode, pressing A sends 0 and 'a' so I can use the 'a'. KeyChar being #0 in many cases obviously makes sense, however I'm failing to see why Key is set to 0 if KeyChar is present.

function GetCharFromVirtualKey(Key: Word): string;
  var Buffer: array[0..255] of Char; 
      ScanCode: Cardinal;
begin
  if Key = VK_PAUSE
    then ScanCode := $45 shl 16
    else ScanCode := MapVirtualKey(Key, 0) shl 16;
  if Key in [33..46, 91..93, 108, 111, 144, 163, 165]
    then ScanCode := ScanCode + $1000000;

  GetKeyNameText(ScanCode, Buffer, SizeOf(Buffer));
  result := Buffer;
end;

procedure TMyForm.Edit1KeyDown(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState);
  var test: string;
begin
  if (KeyChar <> #0) then Key := VkKeyScan(KeyChar) and 255;
  test := GetCharFromVirtualKey(Key);
  // do whatever I want to to with Key and test
end; 

The concrete issue I'm having is that both pressing my regular '1' key and my numpad '1' key sends KeyChar = '1' and Key = 0, so I have no way to differentiate between those two. Is there anything I can do about that ?

Sir Rufo
  • 18,395
  • 2
  • 39
  • 73
DNR
  • 1,619
  • 2
  • 14
  • 22

1 Answers1

5

I'm failing to see why Key is set to 0 if KeyChar is present

Short answer, because that's how FMX.Platform.Win.pas is coded:

WM_CHAR:
  begin
    ch := WideChar(wParam);
    key := 0;
    LForm.KeyDown(key, ch, KeyDataToShiftState(lParam));
    LForm.KeyUp(key, ch, KeyDataToShiftState(lParam));
    Result := 0;
  end;

As for your problem, calling GetKeyState() should do the trick:

procedure TMyForm.Edit1KeyDown(Sender: TObject; var Key: Word; var KeyChar: Char; Shift: TShiftState);
begin
  case KeyChar of
    '0'..'9':
      if GetKeyState(VK_NUMPAD0 + Ord(KeyChar) - Ord('0')) < 0 then
        ShowMessage('Number pad ' + KeyChar + ' pressed')
      else
        ShowMessage('Normal ' + KeyChar + ' pressed');
  end;
end;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Chris Rolliston
  • 4,788
  • 1
  • 16
  • 20
  • This seems to work nicely, thanks. Is there an easier way to adopt that to the entire numpad besides hardcoding statements for VK_SUBTRACT, VK_ADD etc. ? This might get a bit messy, considering I have to account for different keyboard layouts, e.g. my numpad divide key arrives as '7' ... – DNR Feb 23 '14 at 14:38
  • @HeinaBaumstamm - I don't know about your follow-up questions, sorry. – Chris Rolliston Feb 23 '14 at 17:26