Recent

Author Topic: Is there an event that fires when the form loses focus?  (Read 27656 times)

jw

  • Full Member
  • ***
  • Posts: 126
Is there an event that fires when the form loses focus?
« on: April 23, 2010, 04:18:48 pm »
Is there an event that fires when the mainform and or it's child forms lose focus?

lose focus may be a vb term.  It means if someone clicks on another form away from mine to another on the desktop then my form loses focus.

Zoran

  • Hero Member
  • *****
  • Posts: 1988
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: Is there an event that fires when the form loses focus?
« Reply #1 on: April 23, 2010, 07:09:10 pm »
Try Form's OnDeactivate event. Do tests to see if it is what you are looking for. I think it is.
Swan, ZX Spectrum emulator https://github.com/zoran-vucenovic/swan

jw

  • Full Member
  • ***
  • Posts: 126
Re: Is there an event that fires when the form loses focus?
« Reply #2 on: April 23, 2010, 08:35:04 pm »
thanks zoran that's the right event. 

I'm trying to keep a form on the top.  Searching the forums I've seen it done with timers but that seems very wrong.  I was figureing I could do a form.setfocus from this event and keep my form at the top maintaining focus.  But I failed.

Zoran

  • Hero Member
  • *****
  • Posts: 1988
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: Is there an event that fires when the form loses focus?
« Reply #3 on: April 24, 2010, 07:59:45 am »
thanks zoran that's the right event.  

I'm trying to keep a form on the top.  Searching the forums I've seen it done with timers but that seems very wrong.  I was figureing I could do a form.setfocus from this event and keep my form at the top maintaining focus.  But I failed.

The forms have StayOnTop property which works well in Delphi, but in Lazarus it wasn't functioning correctly, I don't know if this functionality is solved by now, try it.
Moreover, even if it works well on one platform, don't be sure it will on another!
Swan, ZX Spectrum emulator https://github.com/zoran-vucenovic/swan

mas steindorff

  • Hero Member
  • *****
  • Posts: 570
Re: Is there an event that fires when the form loses focus?
« Reply #4 on: April 26, 2010, 06:34:38 pm »
If you find a "focus" snippet that works, can you post it? 
I tend to build all of may programs as sub forms so they can be put together in a later project.  while building each app, I have a main form with only a button that shows the working from.  if I hide the main form and show the sub form at start-up, I get the what I desire but the sub form does not have focus and all of the key presses go elsewhere until it is clicked on.
windows 10 &11, Ubuntu 21+ IDE 3.4 general releases

jw

  • Full Member
  • ***
  • Posts: 126
Re: Is there an event that fires when the form loses focus?
« Reply #5 on: May 08, 2010, 10:52:55 pm »
steindorff

I think I can do what your asking for with a windows api call is that ok?



My thoughts were this,

In order to make a window stayontop alway's all I needed to do was set it in the form properties.  The problem is it doesn't work on the main form no matther what you do the stayontop command does nothing.  So I used an api call to make my form stayontop and then the lazarus code would fight me and change the form attributes as soon as the from lost focus.  Seaching the forum I found a post where the api call was placed inside a timer running at 100 ms and this forces the from to maintian the zorder you set for it with respect to the desktop but this seems wrong so I wanted to do away with the timer and put the api call in a function that is called when the from loses focus.  This worked for one time the first time the form loses focus but after that it didn't.  I read in the forums to create a main form and several child forms and the stayontop command would work but the staytontop command is with respect only to the main form and it's child forms so if my main form falls behind another window then all the child forms fall with it their still behind another window but they are on top of the main window so to that end lazarus maintained compatibility with delphi.




anna

  • Sr. Member
  • ****
  • Posts: 426
Re: Is there an event that fires when the form loses focus?
« Reply #6 on: August 10, 2012, 01:31:43 pm »
Try Form's OnDeactivate event. Do tests to see if it is what you are looking for. I think it is.
OnDeactivate works only if focus is switched to another form of project. For example I have project1.exe which creates 2 forms Form1 and Form2 . So Form1 OnDeactivate event triggers if I ckick Form2. But if we have a project2.exe, which creates 1 form: Form1, then OnDeactivate does not trigger if I ckick Notepad window.

So how to hook losing focus in single-window projects ????
WinXP SP3 Pro Russian 32-bit (5.1.2600)

anna

  • Sr. Member
  • ****
  • Posts: 426
Re: Is there an event that fires when the form loses focus?
« Reply #7 on: August 10, 2012, 01:47:49 pm »
I understand, FORM OnDeactivate works as should. I need TApplication.OnDeactivate. But I don't know how to call TApplication.OnDeactivate from unit1.
WinXP SP3 Pro Russian 32-bit (5.1.2600)

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Is there an event that fires when the form loses focus?
« Reply #8 on: August 10, 2012, 02:00:13 pm »
I understand, FORM OnDeactivate works as should. I need TApplication.OnDeactivate. But I don't know how to call TApplication.OnDeactivate from unit1.

You do not call events you attach methods to them to be called by them. EG.

Code: [Select]
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs;

type

  { TForm1 }

  TForm1 = class(TForm)
  private
    { private declarations }
  public
    { public declarations }
    procedure AppDeactivate(Sender: TObject);
    constructor Create(TheOwner: TComponent); override;
  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.AppDeactivate(Sender: TObject);
begin
  ShowMessage('Application.OnDeactivate');
end;

constructor TForm1.Create(TheOwner: TComponent);
begin
  inherited Create(TheOwner);
  Application.OnDeactivate:=@AppDeactivate;
end;

end.

Create a new application and copy paste the above code replacing the default code from the main form unit (preferable before saving it).
Then run the program and see if that does what you want to.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

anna

  • Sr. Member
  • ****
  • Posts: 426
Re: Is there an event that fires when the form loses focus?
« Reply #9 on: August 10, 2012, 02:10:04 pm »
Then run the program and see if that does what you want to.
Thank you a lot! It works fine.
WinXP SP3 Pro Russian 32-bit (5.1.2600)

RAW

  • Hero Member
  • *****
  • Posts: 871
Re: Is there an event that fires when the form loses focus?
« Reply #10 on: December 23, 2016, 03:03:29 am »
I think this way it's easier.... but it looks like there is a bug when running on "Windows 7 x64 Sp1" in combination with the START-Button.

Normally this works very fine for me, but when I click on START and keep the menu open and then click on the Taskbar-Button from the Firefox-Browser, then Label1.Caption = FOCUS and that's wrong, because Firefox has got the Focus. When I switch to AkelPadTextEditor then Label1.Caption still shows "FOCUS".

It looks like this happens only in combination with the START-Button.
Switching between normal programs looks very good...

Code: Pascal  [Select][+][-]
  1. Unit Unit1;
  2.  {$MODE OBJFPC}{$H+}
  3.  
  4. Interface
  5.  USES
  6.   Classes, Forms, StdCtrls;
  7.  
  8.  TYPE
  9.   TForm1 = Class(TForm)
  10.  
  11.    Label1: TLabel;
  12.  
  13.     Procedure FormCreate     (Sender: TObject);
  14.     Procedure FormActivate   (Sender: TObject);
  15.     Procedure FormDeactivate (Sender: TObject);
  16.   End;
  17.  
  18.  VAR
  19.   Form1: TForm1;
  20.  
  21. Implementation
  22.  {$R *.LFM}
  23.  
  24.  
  25. Procedure TForm1.FormCreate(Sender: TObject);
  26.  Begin
  27.   Height  := 300;
  28.   Width   := 500;
  29.   Position:= poDesktopCenter;
  30.  
  31.   Application.OnActivate  := @FormActivate;
  32.   Application.OnDeactivate:= @FormDeactivate;
  33.  End;
  34.  
  35.  
  36. Procedure TForm1.FormActivate(Sender: TObject);
  37.  Begin
  38.   Label1.Caption:= 'FOCUS';
  39.  End;
  40.  
  41.  
  42. Procedure TForm1.FormDeactivate(Sender: TObject);
  43.  Begin
  44.   Label1.Caption:= 'NO FOCUS';
  45.  End;
  46.  
  47. End.
  48.  

User137

  • Hero Member
  • *****
  • Posts: 1791
    • Nxpascal home
Re: Is there an event that fires when the form loses focus?
« Reply #11 on: December 23, 2016, 06:36:38 am »
There is an even easier way to all the application events.

RAW

  • Hero Member
  • *****
  • Posts: 871
Re: Is there an event that fires when the form loses focus?
« Reply #12 on: December 23, 2016, 05:47:05 pm »
@User137
Thank you very much... I overlooked that one completely... all the time...

The problem with the START-Button / START-Menu remains sometimes, but maybe it's my system...  :)
In combination with other programs it works well...

Thanks again... maybe I should take a deeper look into all the other DesignTime-Components...

ASerge

  • Hero Member
  • *****
  • Posts: 2481
Re: Is there an event that fires when the form loses focus?
« Reply #13 on: December 24, 2016, 09:01:49 am »
The problem with the START-Button / START-Menu remains sometimes, but maybe it's my system...  :)
Duplicate WM_ACTIVATEAPP when WM_NCACTIVATE
Example, create base form like this, also avoid its creation in the project source:
Code: Pascal  [Select][+][-]
  1. unit uBaseForm;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Forms, Windows;
  9.  
  10. type
  11.   TBaseForm = class(TForm)
  12.   private
  13.     FOldWndProc: Windows.WNDPROC;
  14.   protected
  15.     procedure CreateWnd; override;
  16.   end;
  17.  
  18. implementation
  19.  
  20. uses InterfaceBase;
  21.  
  22. {$R *.lfm}
  23.  
  24. {$PUSH}
  25. {$WARN 4055 OFF Hint: Conversion between ordinals and pointers is not portable}
  26. function PtrToLong(P: Pointer): LONG_PTR; inline;
  27. begin
  28.   Result := LONG_PTR(P);
  29. end;
  30.  
  31. function LongToPtr(U: LONG_PTR): Pointer; inline;
  32. begin
  33.   Result := Pointer(U);
  34. end;
  35. {$POP}
  36.  
  37. function WndCallback(Wnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
  38. var
  39.   Form: TForm;
  40. begin
  41.   Pointer(Form) := LongToPtr(GetWindowLongPtr(Wnd, GWL_USERDATA));
  42.   if Form is TBaseForm then
  43.     Result := CallWindowProc(TBaseForm(Form).FOldWndProc, Wnd, Msg, wParam, lParam)
  44.   else
  45.     Result := DefWindowProc(Wnd, Msg, wParam, lParam);
  46.   if Msg = WM_NCACTIVATE then
  47.     PostMessage(WidgetSet.AppHandle, WM_ACTIVATEAPP, wParam, lParam);
  48. end;
  49.  
  50. { TBaseForm }
  51.  
  52. procedure TBaseForm.CreateWnd;
  53. var
  54.   SelfWnd: HWND;
  55. begin
  56.   inherited;
  57.   if HandleAllocated then
  58.   begin
  59.     SelfWnd := Handle;
  60.     SetWindowLongPtr(SelfWnd, GWL_USERDATA, PtrToLong(Self));
  61.     FOldWndProc := Windows.WNDPROC(LongToPtr(SetWindowLongPtr(SelfWnd,
  62.       GWL_WNDPROC, PtrToLong(@WndCallback))));
  63.   end;
  64. end;
Then inherited all your forms from this base form:
Code: Pascal  [Select][+][-]
  1. // ...Some form unit
  2. uses
  3.   Classes, {...}uBaseForm;
  4.  
  5. type
  6.   TForm1 = class(TBaseForm)
  7. //...

RAW

  • Hero Member
  • *****
  • Posts: 871
Re: Is there an event that fires when the form loses focus?
« Reply #14 on: December 26, 2016, 04:51:56 pm »
@ASerge
Hey, thank you very much, your code is running very fine.
Right now I can't see anything of that problem... looks like it's vanished...

Now I need to take a look into the User's Guide...
I never used {$PUSH} and {$POP} and right now I don't understand what your code is doing, but maybe I'll get it tomorrow...

Very helpful and interesting code...

Code: Pascal  [Select][+][-]
  1. PROGRAM Project1;
  2.  {$MODE OBJFPC}{$H+}
  3.  
  4.  USES
  5.   Interfaces,
  6.   Forms,
  7.   Unit1;
  8.  
  9.   {$R *.RES}
  10.  
  11. BEGIN
  12.  RequireDerivedFormResource:=True;
  13.   Application.Initialize;
  14.    Form1:= TForm1.Create(Application);
  15.    Form1.Show;
  16.   Application.Run;
  17. END.    
  18. //===========================
  19.  
  20. Unit Unit1;
  21.  {$MODE OBJFPC}{$H+}
  22.  
  23. Interface
  24.  USES
  25.   Classes, Forms, StdCtrls, uBaseForm;
  26.  
  27.  TYPE
  28.   TForm1 = Class(TBaseForm)
  29.  
  30.    ApplicationProperties1: TApplicationProperties;
  31.    Label1                : TLabel;
  32.  
  33.     Procedure FormClose (Sender: TObject; Var CloseAction: TCloseAction);
  34.  
  35.     Procedure ApplicationProperties1Deactivate (Sender: TObject);
  36.     Procedure ApplicationProperties1Activate   (Sender: TObject);
  37.   End;
  38.  
  39.  VAR
  40.   Form1: TForm1;
  41.  
  42. Implementation
  43.  {$R *.LFM}
  44.  
  45.  
  46. Procedure TForm1.FormClose(Sender: TObject; Var CloseAction: TCloseAction);
  47.  Begin
  48.   Application.Terminate;
  49.  End;
  50.  
  51.  
  52. Procedure TForm1.ApplicationProperties1Deactivate(Sender: TObject);
  53.  Begin
  54.   Label1.Caption:= 'Deactivate';
  55.  End;
  56.  
  57.  
  58. Procedure TForm1.ApplicationProperties1Activate(Sender: TObject);
  59.  Begin
  60.   Label1.Caption:= 'Activate';
  61.  End;
  62.  
  63. End.
  64.  

 

TinyPortal © 2005-2018