Recent

Author Topic: How detect a keypress in a Windows program  (Read 1687 times)

creaothceann

  • Full Member
  • ***
  • Posts: 223
Re: How detect a keypress in a Windows program
« Reply #15 on: November 07, 2025, 11:55:55 am »
The application has the focus at all times. There is code that is called from a mouse click event handler, which can run for several minutes (and this time can be unpredictable)

Use a worker TThread so that the code won't block the user interface.

ad1mt

  • Sr. Member
  • ****
  • Posts: 479
    • Mark Taylor's Home Page
Re: How detect a keypress in a Windows program
« Reply #16 on: November 07, 2025, 04:43:51 pm »
On Windows, GetKeyState() relies on the calling thread's local keyboard state, which is updated only during window message processing.  Your event handler doesn't have a message pump of its own, but ShowMessage() does internally...
...  Use GetAsyncKeyState() instead, which uses global keyboard state rather then the calling thread's local keyboard state.
I've been thinking about what you said... is there a way I can create a "message pump" in the code, to enable the key-presses to get through?

PS - I tried using getasynckeystate but it seems to be unreliable... sometimes it works, sometimes it doesn't.

ad1mt

  • Sr. Member
  • ****
  • Posts: 479
    • Mark Taylor's Home Page
Re: How detect a keypress in a Windows program
« Reply #17 on: November 07, 2025, 06:02:41 pm »
Use a worker TThread so that the code won't block the user interface.
I don't think I understand what you mean here.
Please could you help me, by posting a small bit of example code.
Many Thanks.

ad1mt

  • Sr. Member
  • ****
  • Posts: 479
    • Mark Taylor's Home Page
Re: How detect a keypress in a Windows program
« Reply #18 on: November 07, 2025, 06:07:12 pm »
Code: Pascal  [Select][+][-]
  1. type
  2.   TForm1 = class(TForm)
  3.     Timer: TTimer;
  4.     procedure FormClick(Sender: TObject);
  5.     procedure TimerElapsed(Sender: TObject);
  6.     procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  7.   end;
  8.  
  9. procedure TForm1.FormClick(Sender: TObject);
  10. begin
  11.   Timer.Interval := 2000;
  12.   Timer.Enabled := True;
  13. end;
  14.  
  15. procedure TForm1.TimerElapsed(Sender: TObject);
  16. begin
  17.   // do something...
  18. end;
  19.      
  20. procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
  21. begin
  22.   if Key = VK_ESCAPE then
  23.   begin
  24.     Key := 0;
  25.     Timer.Enabled := False;
  26.     Close;
  27.   end;
  28. end;
Thanks for this suggestion.
Having tried & failed with all other suggestions, I'm going to try this one.

creaothceann

  • Full Member
  • ***
  • Posts: 223
Re: How detect a keypress in a Windows program
« Reply #19 on: November 07, 2025, 10:57:38 pm »
Use a worker TThread so that the code won't block the user interface.
I don't think I understand what you mean here.
Please could you help me, by posting a small bit of example code.

I'll try to post an example tomorrow.

ad1mt

  • Sr. Member
  • ****
  • Posts: 479
    • Mark Taylor's Home Page
Re: How detect a keypress in a Windows program
« Reply #20 on: November 08, 2025, 12:06:30 am »
Use a worker TThread so that the code won't block the user interface.
I think I figured-out what you meant... and I got the attached small test project working.
I would be really grateful if you take a look at the code/logic, and see it I've done anything wrong.
I'm a bit dubious about the way I'm sharing a global variable between the two threads/units; although I am careful to make sure that both cannot write at the same time.
I want to make sure I get this right, because I've used the same logic/method in my Checkers program (discussed in a nearby thread).
Thanks.
PS - if you run the program, it waits for a mouse click, then it sets the thread running which waits for the QUIT variable to be set, then the main loop waits until it receives an [ESC] key press, then sets the QUIT variable and then waits for the thread to finish.

PS - this has bugs - see below
« Last Edit: November 08, 2025, 07:48:31 pm by ad1mt »

creaothceann

  • Full Member
  • ***
  • Posts: 223
Re: How detect a keypress in a Windows program
« Reply #21 on: November 08, 2025, 05:03:48 pm »
Here's a sample project of a checkers program with multithreading.

  • U_Form_Main: the GUI managed by the main thread
  • U_Game: the game state + code
  • U_WorkerThread: the thread that does an interruptible task
  • U_Common: some shared constants / types / code
EDIT: the SetSize function is probably broken for SetSize(0, 0), but for some reason there's no error message
« Last Edit: November 08, 2025, 05:18:14 pm by creaothceann »

ad1mt

  • Sr. Member
  • ****
  • Posts: 479
    • Mark Taylor's Home Page
Re: How detect a keypress in a Windows program
« Reply #22 on: November 08, 2025, 07:44:10 pm »
I got the attached small test project working...
...but it had bugs  :o
Fixed in bersion 3.

If you run the program, it waits for a mouse click, then it sets the thread running which waits for the QUIT variable to be set, meanwhile the main loop waits until it receives an [ESC] key press, it then sets the QUIT variable and waits for the thread to finish.
« Last Edit: November 08, 2025, 07:47:03 pm by ad1mt »

creaothceann

  • Full Member
  • ***
  • Posts: 223
Re: How detect a keypress in a Windows program
« Reply #23 on: November 08, 2025, 09:37:38 pm »
If you run the program, it waits for a mouse click, then it sets the thread running which waits for the QUIT variable to be set, meanwhile the main loop waits until it receives an [ESC] key press, it then sets the QUIT variable and waits for the thread to finish

You can just use the TThread.Terminated variable for that, and calling TThread.Terminate sets that variable to true.

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1567
    • Lebeau Software
Re: How detect a keypress in a Windows program
« Reply #24 on: November 09, 2025, 07:49:50 pm »
is there a way I can create a "message pump" in the code, to enable the key-presses to get through?

Josh told you 3 days ago how to do that:

https://forum.lazarus.freepascal.org/index.php/topic,72668.msg569312.html#msg569312
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

 

TinyPortal © 2005-2018