Jump to content
ŁukaszDe

No KeyUp for numpad keys after relese Shift

Recommended Posts

Hello

 

In application I need to know is pressed any key on keyboard.

On keyboard we have two keys INSERT. one normal and another on Numpad.

The second one is working when Num Lock is turned on and need Shift Key pressed.

The problem is with INSERT on Numpad.

 

When you press SHIFT and 0 on numpad then GetKeyState(VK_INSERT)  result is ok, key pressed.

But when you release SHIFT then above function still result is wrong because now preseed is 0, no INSERT. Function result is < 0, which means the key is still pressed.

 

If you try react in FormKeyUp and FormKeyDown then will not appear event for KeyUp(Key = 45) INSERT...

Key 45 (INSERT) left pressed, even when we release numPad 0.

 

Example code:

 

program keytest;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Windows, System.SysUtils;
var
  Key: Integer;
begin
  try
    repeat
      if (GetKeyState(VK_INSERT) < 0) then
        Writeln('INSERT')
      else
        Writeln('0');
    until True;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

 

 

Share this post


Link to post

Maybe a small Sleep(200); in the repeat-until loop may help the OS to process the messageloop ?

Share this post


Link to post

No. You can close application and run again and will be information that INSERT is pressed.

Share this post


Link to post

GetKeyState and related WinAPI functions are broken with Numlock enabled - and you are not the only one suffering from this defect if you google for numpad shift stuck

 

If you release the shift key first it never sees the keyup of the insert key (which the shift key turned the numpad 0 key to).

 

You have to use other ways to do that

Share this post


Link to post

I can't see anything broken.

SHIFT overrides NumLock and CapsLock.

That means, with NumLock ON pressing SHIFT + 0 = pressing insert.

Releasing SHIFT means, you are holding the 0 key, releasing 0 means you are releasing the 0 key, and not Insert.

That's how windows works.

 

Share this post


Link to post

So, it is best to use KeyDown and KeyUp in FMX to determine if any of the two insert keys is currently down?

 

implementation

{$R *.fmx}

uses
  Windows;

var
  IsInsertPressed: Boolean;

procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; var KeyChar: Char;
  Shift: TShiftState);
begin
  case key of
    45:
    begin
      IsInsertPressed := True;
      UpdateCaption;
    end;
  end;
end;

procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word; var KeyChar: Char;
  Shift: TShiftState);
begin
  case key of
    45:
    begin
      IsInsertPressed := False;
      UpdateCaption;
    end;
  end;
  case KeyChar of
    '0':
    begin
      IsInsertPressed := False;
    end;
  end;
  UpdateCaption;
end;

procedure TForm1.UpdateCaption;
begin
  if IsInsertPressed then
    Caption := 'INSERT'
  else
    Caption := '0';
end;

end.

 

Share this post


Link to post
15 hours ago, Attila Kovacs said:

I can't see anything broken.

SHIFT overrides NumLock and CapsLock.

That means, with NumLock ON pressing SHIFT + 0 = pressing insert.

Releasing SHIFT means, you are holding the 0 key, releasing 0 means you are releasing the 0 key, and not Insert.

That's how windows works.

 

I think it is broken - windows is reporting INSERT down, but it is not.

In fact as soon as he releases Shift, he is not pressing Insert anymore, so there should be Shift-up, Insert-up, Zero-down.

Share this post


Link to post

VK_INSERT tests a virtual key not a real key, this is how I understand it after testing.
Windows is reporting the insert STATE - on or off - when you call GetKeyState, possible return values: 0, -1, -127, or -128.
You cannot even tell which of the insert keys or key combinations were used to toggle the state.

 

In VCL, FormKeyPress triggers for KeyDown only, and FormKeyUp does not respond to the numpad numbers at all?
( In FMX, you can use FormKeyUp to successfully detect the '0' up character and know that the key was lifted. )

Share this post


Link to post
22 hours ago, Stefan Glienke said:

You have to use other ways to do that,

Using ScanCode perhaps, in VCL?

unit Unit1;

interface

uses
  Winapi.Windows,
  Winapi.Messages,
  Vcl.Forms;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    ScanCode: Word;
  public
    procedure WMKeyDown(var Msg: TMessage); message WM_KEYDOWN;
    procedure WMKeyUp(var Msg: TMessage); message WM_KEYUp;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  ScanCode := Lo(MapVirtualKey(VK_INSERT, 0));
end;

procedure TForm1.WMKeyDown(var Msg: TMessage);
var
  w: Word;
  b: Byte;
begin
  w := Msg.LParamHi;
  b := LoByte(w);
  if b = ScanCode then
    Caption := 'down';
  inherited;
end;

procedure TForm1.WMKeyUp(var Msg: TMessage);
var
  w: Word;
  b: Byte;
begin
  w := Msg.LParamHi;
  b := LoByte(w);
  if b = ScanCode then
    Caption := 'up';
  inherited;
end;

end.

 

Edited by Gustav Schubert

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×