0

我正在尝试确定在按钮(FMX、XE3)的 OnKeyDown 中按下的键,但我目前发现自己无法区分小键盘键和常规键...

根据我按下的键,我可以使用 Key 或 KeyChar 来找出按下了哪个键。例如,按下F1发送 112 和 #0 以便我可以使用 VkCode,按下A发送 0 和“a”以便我可以使用“a”。在许多情况下,KeyChar 是 #0 显然是有道理的,但是如果 KeyChar 存在,我看不出为什么 Key 设置为 0。

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; 

我遇到的具体问题是,按我的常规“1”键和小键盘“1”键都会发送 KeyChar = '1' 和 Key = 0,所以我无法区分这两者。我能做些什么吗?

4

1 回答 1

5

如果存在 KeyChar,我看不到为什么 Key 设置为 0

简短的回答,因为这FMX.Platform.Win.pas就是编码方式:

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

至于你的问题,打电话GetKeyState()应该可以解决问题:

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;
于 2014-02-23T13:31:54.603 回答