Recent

Author Topic: Popup Form to close when focus is lost  (Read 873 times)

daniel_sap

  • Full Member
  • ***
  • Posts: 115
Popup Form to close when focus is lost
« on: July 09, 2025, 12:56:37 pm »
Hi,
I created descendant of TForm which implements behavior like Popup Window.
But the form is not closing itself after clicking outside of it.
I tried with SetCapture and Deactivate but still nothing happens.

Code: Pascal  [Select][+][-]
  1. unit DSPopupForm;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Forms, Classes, LMessages;
  9.  
  10. type
  11.  
  12.   { TDSPopupForm }
  13.  
  14.   TDSPopupForm = class(TForm)
  15.   protected
  16.     procedure Deactivate; override;
  17.     procedure WMLButtonDown(var AMessage: TLMLButtonDown); message LM_LBUTTONDOWN;
  18.     procedure DoClose(var CloseAction: TCloseAction); override;
  19.   public
  20.     constructor Create(TheOwner: TComponent); override;
  21.     procedure popup(x, y: Integer);
  22.   end;
  23.  
  24. implementation
  25.  
  26. uses
  27.   Controls, LCLIntf;
  28.  
  29. { TDSPopupForm }
  30.  
  31. constructor TDSPopupForm.Create(TheOwner: TComponent);
  32. begin
  33.   inherited Create(TheOwner);
  34.   BorderStyle := bsNone;
  35.   FormStyle := fsStayOnTop;
  36. end;
  37.  
  38. procedure TDSPopupForm.popup(x, y: Integer);
  39. begin
  40.   Left := X;
  41.   Top := Y;
  42.   Show;
  43.   Activate;
  44.   SetCapture(Handle);
  45. end;
  46.  
  47. procedure TDSPopupForm.Deactivate;
  48. begin
  49.   inherited Deactivate;
  50.   Close;
  51. end;
  52.  
  53. procedure TDSPopupForm.WMLButtonDown(var AMessage: TLMLButtonDown);
  54. var
  55.   MousePos: TPoint;
  56. begin
  57.   MousePos := Mouse.CursorPos;
  58.   if not PtInRect(BoundsRect, MousePos) then
  59.   begin
  60.     Close;
  61.   end
  62.   else
  63.   begin
  64.     inherited;
  65.   end;
  66. end;
  67.  
  68. procedure TDSPopupForm.DoClose(var CloseAction: TCloseAction);
  69. begin
  70.   ReleaseCapture;
  71.   inherited;
  72. end;
  73.  
  74. end.
  75.  

May be you can point something I cannot see or suggest some work direction

AI suggested to use
Code: Pascal  [Select][+][-]
  1.   FormStyle := fsPopup;
  2.  
instead of
Code: Pascal  [Select][+][-]
  1.   FormStyle := fsStayOnTop;
  2.  
Which I thought will make the form behave as Popup, but actually fsPopup doesn't exists at all in the enumeration.

Lazarus 4.0RC1 (rev t-fixes-4-58-g43d904ed50) FPC 3.2.2 x86_64-win64-win32/win64

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 12429
  • Debugger - SynEdit - and more
    • wiki
Re: Popup Form to close when focus is lost
« Reply #1 on: July 09, 2025, 01:25:16 pm »
"Deactivate" iirc is only if your entire app is "switched away from".

Try  (not tested)
Code: Pascal  [Select][+][-]
  1.     procedure WMKillFocus(var Msg: TWMKillFocus); message WM_KILLFOCUS;
  2.  

May need more checks if you have focus-able controls inside that form....

You still want to keep Deactivate, as I am not sure you get a killfocus, if there is a deactivate


« Last Edit: July 09, 2025, 01:26:52 pm by Martin_fr »

Thaddy

  • Hero Member
  • *****
  • Posts: 19272
  • Glad to be alive.
Re: Popup Form to close when focus is lost
« Reply #2 on: July 09, 2025, 01:39:50 pm »
If your popup form is the child of a real popup window then it might work...
Pass the popup as the owner.

Two forms: mainform with a popup menu:
Code: Pascal  [Select][+][-]
  1. unit popupmain;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, Menus, popup2;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     PopupMenu1: TPopupMenu;
  16.     procedure FormActivate(Sender: TObject);
  17.     procedure PopupMenu1Popup(Sender: TObject);
  18.   private
  19.  
  20.   public
  21.  
  22.   end;
  23.  
  24. var
  25.   Form1: TForm1;
  26.  
  27. implementation
  28.  
  29. {$R *.lfm}
  30.  
  31. { TForm1 }
  32.  
  33. procedure TForm1.PopupMenu1Popup(Sender: TObject);
  34. begin
  35.    popup2.Form2.show;;
  36. end;
  37.  
  38. procedure TForm1.FormActivate(Sender: TObject);
  39. begin
  40.   popup2.Form2.hide;
  41. end;
  42.  
  43. end

The second form is just a form:
Code: Pascal  [Select][+][-]
  1. unit popup2;
  2.  
  3. {$mode ObjFPC}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Menus;
  9.  
  10. type
  11.  
  12.   { TForm2 }
  13.  
  14.   TForm2 = class(TForm)
  15.    private
  16.  
  17.   public
  18.  
  19.   end;
  20.  
  21. var
  22.   Form2: TForm2;
  23.  
  24. implementation
  25. uses popupmain; // <-- mainform
  26.  
  27. {$R *.lfm}
  28.  
  29. { TForm2 }
  30.  
  31. end.
That's all.


« Last Edit: July 09, 2025, 03:04:36 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

nanobit

  • Full Member
  • ***
  • Posts: 192

Thaddy

  • Hero Member
  • *****
  • Posts: 19272
  • Glad to be alive.
Re: Popup Form to close when focus is lost
« Reply #4 on: July 09, 2025, 02:10:55 pm »
Both of these are way to complex. See my example, it is really easy.
Right click on main form pops up the popupform, which has focus.
Now when the main form is focused again the popup disappears.
That was all that was asked wasn't it?

By using a real popup I saved hundreds of lines of code compared to the examples you mentioned.
« Last Edit: July 09, 2025, 03:08:01 pm by Thaddy »
objects are fine constructs. You can even initialize them with constructors.

 

TinyPortal © 2005-2018