Recent

Author Topic: How can I capture all key presses despite what component is in focus?  (Read 935 times)

FragmentedCurve

  • Newbie
  • Posts: 4
Let's say I have the following class,

Code: Pascal  [Select][+][-]
  1. TMainForm = class(TForm)
  2.   InputText: TLabel;
  3.  
  4.   ResetButton: TButton;
  5.   BackButton: TButton;
  6.   NextButton: TButton;
  7.  
  8.   procedure FormCreate(Sender: TObject);
  9.   procedure HandleKeyPress(Sender: TObject; var Key: char);  
  10. end;

HandleKeyPress updates the caption in InputText. How can I force HandleKeyPress to be called even if one of the 3 buttons are focused?

dsiders

  • Hero Member
  • *****
  • Posts: 915
Let's say I have the following class,

Code: Pascal  [Select][+][-]
  1. TMainForm = class(TForm)
  2.   InputText: TLabel;
  3.  
  4.   ResetButton: TButton;
  5.   BackButton: TButton;
  6.   NextButton: TButton;
  7.  
  8.   procedure FormCreate(Sender: TObject);
  9.   procedure HandleKeyPress(Sender: TObject; var Key: char);  
  10. end;

HandleKeyPress updates the caption in InputText. How can I force HandleKeyPress to be called even if one of the 3 buttons are focused?

Focused or hovered? Controls have OnEnter and OnExit event handlers for focus changes. They also have OnMouseEnter and OnMouseLeave handlers for mouse hover.
Preview Lazarus 3.99 documentation at: https://dsiders.gitlab.io/lazdocsnext

Handoko

  • Hero Member
  • *****
  • Posts: 4934
  • My goal: build my own game engine using Lazarus
Maybe:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, Forms, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     Button2: TButton;
  17.     Button3: TButton;
  18.     Label1: TLabel;
  19.     procedure FormCreate(Sender: TObject);
  20.     procedure KeyPress(Sender: TObject; var Key: char); virtual;
  21.   end;
  22.  
  23. var
  24.   Form1: TForm1;
  25.  
  26. implementation
  27.  
  28. {$R *.lfm}
  29.  
  30. { TForm1 }
  31.  
  32. procedure TForm1.FormCreate(Sender: TObject);
  33. begin
  34.   Button1.OnKeyPress := @KeyPress;
  35.   Button2.OnKeyPress := @KeyPress;
  36.   Button3.OnKeyPress := @KeyPress;
  37. end;
  38.  
  39. procedure TForm1.KeyPress(Sender: TObject; var Key: char);
  40. var
  41.   S: string;
  42. begin
  43.   if Sender = Button1 then
  44.     S := 'first button.'
  45.   else
  46.     if Sender = Button2 then
  47.       S := 'second button.'
  48.     else
  49.       if Sender = Button3 then
  50.         S := 'third button.'
  51.       else Exit;
  52.   Label1.Caption := Key + ' is pressed on the ' + S;
  53. end;
  54.  
  55. end.
« Last Edit: June 04, 2023, 04:02:16 am by Handoko »

FragmentedCurve

  • Newbie
  • Posts: 4
Focused or hovered? Controls have OnEnter and OnExit event handlers for focus changes. They also have OnMouseEnter and OnMouseLeave handlers for mouse hover.

All the above. I'd like to capture all keyboard input under all conditions. Even if a TEdit instance is entered/focused/active/etc.

FragmentedCurve

  • Newbie
  • Posts: 4
Maybe:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, Forms, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     Button2: TButton;
  17.     Button3: TButton;
  18.     Label1: TLabel;
  19.     procedure FormCreate(Sender: TObject);
  20.     procedure KeyPress(Sender: TObject; var Key: char); virtual;
  21.   end;
  22.  
  23. var
  24.   Form1: TForm1;
  25.  
  26. implementation
  27.  
  28. {$R *.lfm}
  29.  
  30. { TForm1 }
  31.  
  32. procedure TForm1.FormCreate(Sender: TObject);
  33. begin
  34.   Button1.OnKeyPress := @KeyPress;
  35.   Button2.OnKeyPress := @KeyPress;
  36.   Button3.OnKeyPress := @KeyPress;
  37. end;
  38.  
  39. procedure TForm1.KeyPress(Sender: TObject; var Key: char);
  40. var
  41.   S: string;
  42. begin
  43.   if Sender = Button1 then
  44.     S := 'first button.'
  45.   else
  46.     if Sender = Button2 then
  47.       S := 'second button.'
  48.     else
  49.       if Sender = Button3 then
  50.         S := 'third button.'
  51.       else Exit;
  52.   Label1.Caption := Key + ' is pressed on the ' + S;
  53. end;
  54.  
  55. end.

I'd rather not do it this way for two reasons: 1) I'd have to do this for every widget in the window which is more than the example in this post. 2) The keys are still be handled by the buttons. If the user hits enter, KeyPress does catch it but so does the button which means the button is clicked.

Edit: If you can prevent the second, this isn't so bad.
« Last Edit: June 04, 2023, 04:36:28 am by FragmentedCurve »

FragmentedCurve

  • Newbie
  • Posts: 4
Code: Pascal  [Select][+][-]
  1. procedure TForm1.KeyPress(Sender: TObject; var Key: char);
  2. var
  3.   S: string;
  4. begin
  5.   if Sender = Button1 then
  6.     S := 'first button.'
  7.   else
  8.     if Sender = Button2 then
  9.       S := 'second button.'
  10.     else
  11.       if Sender = Button3 then
  12.         S := 'third button.'
  13.       else Exit;
  14.   Label1.Caption := Key + ' is pressed on the ' + S;
  15.  
  16.   DefocusControl(Sender as TWinControl, False); // Seems to work
  17. end;

I'm not sure if this is a good way of doing it, but it is working.

Handoko

  • Hero Member
  • *****
  • Posts: 4934
  • My goal: build my own game engine using Lazarus
How about this:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, Controls, Forms, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     Button1: TButton;
  16.     Button2: TButton;
  17.     Button3: TButton;
  18.     CheckBox1: TCheckBox;
  19.     Edit1: TEdit;
  20.     Label1: TLabel;
  21.     procedure FormCreate(Sender: TObject);
  22.     procedure KeyPress(Sender: TObject; var Key: char); virtual;
  23.   end;
  24.  
  25. var
  26.   Form1: TForm1;
  27.  
  28. implementation
  29.  
  30. {$R *.lfm}
  31.  
  32. { TForm1 }
  33.  
  34. procedure TForm1.FormCreate(Sender: TObject);
  35. var
  36.   i: Integer;
  37. begin
  38.   for i := 0 to ComponentCount-1 do
  39.   begin
  40.     if not(Controls[i] is TWinControl) then Continue;
  41.     (Controls[i] as TWinControl).OnKeyPress := @KeyPress;
  42.   end;
  43. end;
  44.  
  45. procedure TForm1.KeyPress(Sender: TObject; var Key: char);
  46. var
  47.   S1, S2: string;
  48. begin
  49.   if not(Sender is TWinControl) then Exit;
  50.   S1 := (Sender as TWinControl).Name;
  51.   case Key of
  52.     #13: S2 := '[Enter]';
  53.     ' ': S2 := '[Space]';
  54.     else S2 := Key;
  55.   end;
  56.   Label1.Caption := S2 + ' is pressed on ' + S1;
  57. end;
  58.  
  59. end.

Bart

  • Hero Member
  • *****
  • Posts: 5070
    • Bart en Mariska's Webstek
Isn't that what TForm.KeyPreView is for?

Bart

jamie

  • Hero Member
  • *****
  • Posts: 5691
look at the TApplication component, second tab.
The only true wisdom is knowing you know nothing

Zvoni

  • Hero Member
  • *****
  • Posts: 1950
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

jcmontherock

  • Full Member
  • ***
  • Posts: 206
Re: How can I capture all key presses despite what component is in focus?
« Reply #10 on: June 05, 2023, 10:21:51 am »
Do you know the difference between TForm.OnKeyPress and TForm.OnKeyDown ?
Windows 11 UTF8 64 - Lazarus 3.0RC1 64 - FPC 3.2.2

jamie

  • Hero Member
  • *****
  • Posts: 5691
Re: How can I capture all key presses despite what component is in focus?
« Reply #11 on: June 05, 2023, 12:25:13 pm »
KeyPress is the translation of Key down and Keyup and it carries translated information, whereas the up and down events use virtual key values, which not directly to normal character values.

 You can find a chart listing the Virtual Key values.
The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018