Recent

Author Topic: What am I missing here? [SOLVED]  (Read 619 times)

Ten_Mile_Hike

  • Full Member
  • ***
  • Posts: 149
What am I missing here? [SOLVED]
« on: June 14, 2026, 08:59:43 pm »
UPDATE... Deactivate doesn't work like I thought that it did...SORRY!!!

Code: Text  [Select][+][-]
  1.  Win11, Lazarus 4.8, Error happens when running the .exe both inside and external to the IDE
  2. ----------------
  3. The following code only ever shows "Activate" when program is initially started.
  4. "Deactivate" NEVER fires and "Activate" NEVER fires again after initial startup
  5. despite the fact that I start a text editor then switch back to the program
  6. ==================
  7. LFM is:
  8. object Form1: TForm1
  9.   Left = 477
  10.   Height = 240
  11.   Top = 164
  12.   Width = 320
  13.   Caption = '0'
  14.   DesignTimePPI = 120
  15.   LCLVersion = '4.8.0.0'
  16.   OnActivate = FormActivate
  17.   OnDeactivate = FormDeactivate
  18. end
  19. =================
  20. So Events are assigned normally
  21. WHAT AM I MISSING???
  22.  



Code: Pascal  [Select][+][-]
  1. unit Unit1;{$mode objfpc}{$H+}
  2.  
  3. interface
  4.  
  5. uses Classes, StdCtrls, SysUtils, Forms, Controls, Graphics, Dialogs;
  6.  
  7. type { TForm1 }
  8.   TForm1 = class(TForm)
  9.     procedure FormActivate(Sender: TObject);
  10.     procedure FormDeactivate(Sender: TObject);
  11.   end;
  12.  
  13. var
  14.   Form1: TForm1;
  15.  
  16. implementation{$R *.lfm}{ TForm1 }
  17.  
  18.  
  19. // OnActivate = FormActivate in Object Inspector
  20. // On Deactivate = FormDeactivate in Object Inspector
  21. procedure TForm1.FormActivate(Sender: TObject);
  22. begin
  23.   ShowMessage('Activate');
  24. end;
  25.  
  26. procedure TForm1.FormDeactivate(Sender: TObject);
  27. begin
  28.   ShowMessage('Deactivate');
  29. end;
  30.  
  31. end.
« Last Edit: June 14, 2026, 09:05:50 pm by Ten_Mile_Hike »
When any government, or any church for that matter, undertakes to say to its subjects, This you may not read, this you
must not see, this you are forbidden to know, the end result is tyranny and oppression no matter how holy the motives.

Robert A. Heinlein

LeP

  • Sr. Member
  • ****
  • Posts: 428
Re: What am I missing here? [SOLVED]
« Reply #1 on: June 14, 2026, 10:55:10 pm »
Note from Windows:
The OnActivate event of the application (TApplication), not the form, occurs when Windows switches control from another application.
« Last Edit: June 14, 2026, 10:56:51 pm by LeP »
Un Sistema per domarli, un IDE per trovarli, un codice per ghermirli e nel framework incatenarli.
An operating system to tame them, an IDE to find them, a code to catch them and in the framework chain them.

Handoko

  • Hero Member
  • *****
  • Posts: 5557
  • My goal: build my own game engine using Lazarus
Re: What am I missing here? [SOLVED]
« Reply #2 on: June 15, 2026, 05:45:28 am »
@Ten_Mile_Hike

I quickly wrote a demo for you:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, StdCtrls, ExtCtrls, Unit2;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     IdleTimer1: TIdleTimer;
  16.     Memo1: TMemo;
  17.     procedure FormActivate(Sender: TObject);
  18.     procedure FormCreate(Sender: TObject);
  19.     procedure FormDeactivate(Sender: TObject);
  20.   private
  21.     procedure RunOnce(Sender: TObject);
  22.   end;
  23.  
  24. var
  25.   Form1: TForm1;
  26.  
  27. implementation
  28.  
  29. {$R *.lfm}
  30.  
  31. { TForm1 }
  32.  
  33. procedure TForm1.FormCreate(Sender: TObject);
  34. begin
  35.   IdleTimer1.OnTimer  := @RunOnce;
  36.   IdleTimer1.Interval := 100;
  37.   Memo1.Clear;
  38.   Memo1.ReadOnly := True;
  39. end;
  40.  
  41. procedure TForm1.FormDeactivate(Sender: TObject);
  42. var
  43.   S: string;
  44. begin
  45.   S := TimeToStr(Now);
  46.   Memo1.Lines.Add(S + ': Form1 deactivated');
  47. end;
  48.  
  49. procedure TForm1.FormActivate(Sender: TObject);
  50. var
  51.   S: string;
  52. begin
  53.   S := TimeToStr(Now);
  54.   Memo1.Lines.Add(S + ': Form1 activated');
  55. end;
  56.  
  57. procedure TForm1.RunOnce(Sender: TObject);
  58. begin
  59.   IdleTimer1.OnTimer := nil;
  60.   Form2.Left := Form1.Left + Form1.Width + 20;
  61.   Form2.Top  := Form1.Top;
  62.   Form2.Show;
  63. end;
  64.  
  65. end.

Code: Pascal  [Select][+][-]
  1. unit Unit2;
  2.  
  3. {$mode ObjFPC}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TForm2 }
  13.  
  14.   TForm2 = class(TForm)
  15.     Memo1: TMemo;
  16.     procedure FormActivate(Sender: TObject);
  17.     procedure FormCreate(Sender: TObject);
  18.     procedure FormDeactivate(Sender: TObject);
  19.   end;
  20.  
  21. var
  22.   Form2: TForm2;
  23.  
  24. implementation
  25.  
  26. {$R *.lfm}
  27.  
  28. { TForm2 }
  29.  
  30. procedure TForm2.FormCreate(Sender: TObject);
  31. begin
  32.   Memo1.Clear;
  33.   Memo1.ReadOnly := True;
  34. end;
  35.  
  36. procedure TForm2.FormDeactivate(Sender: TObject);
  37. var
  38.   S: string;
  39. begin
  40.   S := TimeToStr(Now);
  41.   Memo1.Lines.Add(S + ': Form2 deactivated');
  42. end;
  43.  
  44. procedure TForm2.FormActivate(Sender: TObject);
  45. var
  46.   S: string;
  47. begin
  48.   S := TimeToStr(Now);
  49.   Memo1.Lines.Add(S + ': Form2 activated');end;
  50.  
  51. end.

Ten_Mile_Hike

  • Full Member
  • ***
  • Posts: 149
Re: What am I missing here? [SOLVED]
« Reply #3 on: June 15, 2026, 09:11:10 pm »
@Handoko
I finally decided that what I wanted was to be notified when another Windows program took or gave back focus. Not another Form within my app doing so. OnActivate, OnDeactivate don't fire (to my surprise) when that happens.
I finally accomplished this by the following code that keeps a log of what external apps have focus at all times.
Code: Pascal  [Select][+][-]
  1. unit Unit1;{$mode objfpc}{$H+}interface
  2. uses Classes, StdCtrls,SysUtils, Forms, Dialogs, Windows, ExtCtrls, Controls;
  3. type
  4.  
  5.   { TForm1 }
  6.  
  7.   TForm1 = class(TForm)
  8.     Memo1:TMemo;
  9.     Timer1: TTimer;
  10.     procedure Timer1Timer(Sender: TObject);
  11.   private
  12.     function GetForegroundProcessName: string;
  13.     procedure CheckForeground;
  14.   end;
  15. var Form1: TForm1;implementation{$R *.lfm}
  16.  
  17. Procedure TForm1.Timer1Timer(Sender: TObject);
  18. begin
  19.   CheckForeground;
  20. end;
  21.  
  22. Procedure TForm1.CheckForeground;
  23. var S:String;
  24. begin
  25.   S:=Caption;
  26.   Caption := 'Foreground:   ' + GetForegroundProcessName;
  27.   if S<>Caption then
  28.   Begin
  29.    Memo1.lines.add(Datetimetostr(now)+'  '+Caption);
  30.    Memo1.lines.SaveToFile('Memo1.txt');
  31.   end;
  32. end;
  33.  
  34. Function TForm1.GetForegroundProcessName: string;
  35. var
  36.   hWnd: qword; //Windows.HWND;
  37.   PID: DWORD;
  38.   hProcess: THandle;
  39.   Buffer: array[0..MAX_PATH - 1] of WideChar;
  40.   Size: DWORD;
  41. begin
  42.   Result := '';
  43.   hWnd := GetForegroundWindow;
  44.   if hWnd = 0 then Exit;
  45.   GetWindowThreadProcessId(hWnd, @PID);
  46.   if PID = 0 then Exit;
  47.   hProcess := OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, False, PID);
  48.   if hProcess = 0 then Exit;
  49.   try
  50.     Size := MAX_PATH;
  51.     if QueryFullProcessImageNameW(hProcess, 0, Buffer, @Size)
  52.      then Result := ExtractFileName(String(Buffer))
  53.      else Result := 'unknown.exe';
  54.   finally
  55.     CloseHandle(hProcess);
  56.   end;
  57. end;
  58. end.
When any government, or any church for that matter, undertakes to say to its subjects, This you may not read, this you
must not see, this you are forbidden to know, the end result is tyranny and oppression no matter how holy the motives.

Robert A. Heinlein

Handoko

  • Hero Member
  • *****
  • Posts: 5557
  • My goal: build my own game engine using Lazarus
Re: What am I missing here? [SOLVED]
« Reply #4 on: June 16, 2026, 03:32:58 am »
Nice trick.

I would use TApplicationProperties, which is cross-platform. The code below showing a circle stop moving if the program loses focus:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, ExtCtrls;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     ApplicationProperties1: TApplicationProperties;
  16.     Shape1: TShape;
  17.     Timer1: TTimer;
  18.     procedure ApplicationProperties1Activate(Sender: TObject);
  19.     procedure ApplicationProperties1Deactivate(Sender: TObject);
  20.     procedure FormCreate(Sender: TObject);
  21.   private
  22.     procedure Animate(Sender: TObject);
  23.   end;
  24.  
  25. var
  26.   Form1: TForm1;
  27.  
  28. implementation
  29.  
  30. const
  31.   OffsetX: ShortInt = 3;
  32.   OffsetY: ShortInt = 3;
  33.  
  34. {$R *.lfm}
  35.  
  36. { TForm1 }
  37.  
  38. procedure TForm1.FormCreate(Sender: TObject);
  39. begin
  40.   Timer1.Interval := 20;
  41.   Timer1.OnTimer  := @Animate;
  42. end;
  43.  
  44. procedure TForm1.ApplicationProperties1Activate(Sender: TObject);
  45. begin
  46.   Timer1.Enabled := True;
  47.   Caption := 'Running';
  48. end;
  49.  
  50. procedure TForm1.ApplicationProperties1Deactivate(Sender: TObject);
  51. begin
  52.   Timer1.Enabled := False;
  53.   Caption := 'Paused';
  54. end;
  55.  
  56. procedure TForm1.Animate(Sender: TObject);
  57. begin
  58.   Shape1.Left := Shape1.Left + OffsetX;
  59.   Shape1.Top  := Shape1.Top  + OffsetY;
  60.   if Shape1.Left <= 0 then OffsetX := Random(10) + 3;
  61.   if (Shape1.Left + Shape1.Width) >= Width then OffsetX := -Random(10) - 3;
  62.   if Shape1.Top <= 0 then OffsetY := Random(10) + 3;
  63.   if (Shape1.Top + Shape1.Height) >= Height then OffsetY := -Random(10) - 3;
  64. end;
  65.  
  66. end.
« Last Edit: June 16, 2026, 03:36:22 am by Handoko »

loaded

  • Hero Member
  • *****
  • Posts: 880
Re: What am I missing here? [SOLVED]
« Reply #5 on: June 16, 2026, 08:11:06 am »
...
I would use TApplicationProperties, which is cross-platform. The code below showing a circle stop moving if the program loses focus:
...

Thanks for the example, Handoko.
However, the project still appears to be running when minimized...
The more memory computers have, the less memory people seem to use. 😅

Thaddy

  • Hero Member
  • *****
  • Posts: 19388
  • Glad to be alive.
Re: What am I missing here? [SOLVED]
« Reply #6 on: June 17, 2026, 03:39:02 pm »
However, the project still appears to be running when minimized...
Of course it is still running. It just ignores paint messages, etc, because these are not needed when minimized..No screen updates to process.
objects are fine constructs. You can even initialize them with constructors.

 

TinyPortal © 2005-2018