Recent

Author Topic: Close Form  (Read 30810 times)

Old Dog

  • New Member
  • *
  • Posts: 17
Close Form
« on: February 03, 2011, 06:40:09 am »
I have an application with a main form.  From the menu of the main form I open a second form embeded in a panel on main form.  Panel is visible := false until second form is opened, then visible := true.  On the second form I have a button than I want to use to close the second form and go back to the main form with panel visible := false.  Any suggestions?

exdatis

  • Hero Member
  • *****
  • Posts: 668
    • exdatis
Re: Close Form
« Reply #1 on: February 03, 2011, 07:21:15 am »
Panel.Visible:= False;(not need)
SecondForm:= TSecondForm.Create(self);
SecondForm.Parent:= Panel;
SecondForm.Left:= <integer>;
SecondForm.Top:= <integer>;
SecondForm.Show;

{on close second form, just...}
CloseAction:= caFree;
SecondForm:= nil; {and panel.visible = True} //nothing more...

exdatis

  • Hero Member
  • *****
  • Posts: 668
    • exdatis
Re: Close Form
« Reply #2 on: February 03, 2011, 07:29:02 am »
I have a public procedure OnNewForm
--------
  if Panel.ControlCount>2 then {Control[0] = logo, Control[1] = hyperlink}
    Panel.Controls[2].Destroy;{close form}
--------
In that case:
SecondForm:= TSecondForm.Create(self);
OnNewForm;
..parent
..position
..show
« Last Edit: February 03, 2011, 07:33:45 am by exdatis »

Old Dog

  • New Member
  • *
  • Posts: 17
Re: Close Form
« Reply #3 on: February 03, 2011, 06:35:29 pm »
still confused.

currently I open form2(unit2) with by a menu item on form1(unit1) using:

Code: [Select]
function EmbedForm(FormClass: TFormClass; Parent: TWinControl): TForm;
var
  Instance: TForm;
  Ctrl: TControl;
beginonm
  Instance:=TForm(FormClass.NewInstance);
  Instance.Create(Parent);
  while Instance.ControlCount > 0 do begin
    Ctrl:=Instance.Controls[0];
    Ctrl.Parent:=Parent;
  end;
  EmbedForm:=Instance;
end;
-----------------
onMenuItemClick...
    Panel1.visible := true;
    ftmp := EmbedForm(TFormStates,Panel1);

I found embedform somewhere in the forum.  if i put a temporary button on the main form with this code:
Code: [Select]
procedure TFormMain.Button1Click(Sender: TObject);
var
  itmp:integer;
begin
   for itmp := panel1.ControlCount downto 1 do
     panel1.controls[0].destroy;
  panel1.visible:=false;
end;

i can close form2.  I want to close form2 from form2,  but I can't seem to do it.

Old Dog

  • New Member
  • *
  • Posts: 17
Re: Close Form
« Reply #4 on: February 20, 2011, 10:09:09 pm »
Think I found a solution.

I had previously created a library unit for variables, functions and procedures that are used by multiple forms.  I put the following variable in that unit:
Code: [Select]
    FormInPanel : TForm;
In the main form I open the subform with:
Code: [Select]
procedure TFormMain.OpenFormInPanel;
begin
  FormInPanel.Parent :=Panel1;
  FormInPanel.Left := 0;
  FormInPanel.Top := 0;
  FormInPanel.Width := FormInPanel.parent.ClientWidth;
  FormInPanel.Height := FormInPanel.Parent.ClientHeight;
  FormInPanel.parent.visible := true;
  FormInPanel.Show;
end;

procedure TFormMain.MenuItemStatesClick(Sender: TObject);
begin
  FormInPanel := TFormStates.Create(Self);
  OpenFormInPanel;
end;
I can then close the subform from itself with:
Code: [Select]
procedure TFormStates.ButtonCloseClick(Sender: TObject);
begin
  DbfStates.Close;
  FormInPanel.close;
  FormInPanel.parent.Visible := False;
end;

I am still open to better ideas.

eny

  • Hero Member
  • *****
  • Posts: 1665
Re: Close Form
« Reply #5 on: February 20, 2011, 10:48:04 pm »
You're using pretty tight coupling, relying on a global variable and the fact the parent of the child form has a property called visible.

What I normally do for such situations is define an event handler.
1. The main form has a 'child is closing' event handler.
2. The child form receives this event handler procedure.
3. When the child is closed it calls the event handler.

Something like:
Code: Pascal  [Select][+][-]
  1.   // Somewhere in the main form:
  2.   TfrmMain(TForm)
  3.   //...
  4.     procedure ChildIsDestroyedNotifier;
  5.   end;
  6.  
  7.   procedure TfrmMain.ChildIsDestroyedNotifier;
  8.   begin
  9.     // Do whatever processing is necessary when an embedded form/child closes
  10.     Panel.Visible := false;  // For example
  11.   end;
  12.  
  13.   // And when the child is created
  14.   procedure TfrmMain.OpenFormInPanel;
  15.   begin  
  16.     // ...
  17.     FormInPanel.OnCloseNotifier := @ChildIsDestroyedNotifier;
  18.   end;
  19.  
  20.   //...
  21.   // In the child form:
  22.   TfrmChild(TForm)
  23.     OnCloseHandler: TProcedureOfObject;
  24.   end;
  25.  
  26.   //...
  27.   // Now when the child form is closed
  28.   procedure TfrmChild.FormClose(Sender: TObject; var CloseAction: TCloseAction);
  29.   begin
  30.     // Signal the user of this form that it's about to close...
  31.     if assigned(OnCloseHandler) then
  32.       OnCloseHandler();
  33.   end;

(OnCloseHandler should of course be a property that sets a private field, but you get the idea.)
All posts based on: Win11; stable Lazarus 4_4  (x64) 2026-02-12 (unless specified otherwise...)

Old Dog

  • New Member
  • *
  • Posts: 17
Re: Close Form
« Reply #6 on: February 21, 2011, 03:43:05 am »
Not completely.  Are you suggesting that I get rid of the global variable?
If so, what replaces it?

I don't understand what you mean by setting a private field.

eny

  • Hero Member
  • *****
  • Posts: 1665
Re: Close Form
« Reply #7 on: February 21, 2011, 08:53:53 am »
Not completely.  Are you suggesting that I get rid of the global variable?
Yes (getting rid of global variables is always a good idea.)

Quote
If so, what replaces it?
The event handler: if the embedded form is closed, the parent is notified via the message.

Quote
I don't understand what you mean by setting a private field.

Code: Pascal  [Select][+][-]
  1.   // In the child form:
  2.   TfrmChild(TForm)
  3.   private
  4.     FOnCloseHandler: TProcedureOfObject;
  5.   public
  6.     OnCloseHandler: TProcedureOfObject read FOnCloseHandler write FOnCloseHandler;
  7.   end;
... the usual way of handling properties.
All posts based on: Win11; stable Lazarus 4_4  (x64) 2026-02-12 (unless specified otherwise...)

Old Dog

  • New Member
  • *
  • Posts: 17
Re: Close Form
« Reply #8 on: February 22, 2011, 02:09:03 am »
OK, I've got the code in the child form.  Seems to be fine.

But I must still be missing something.  I commented out the global variable from the library unit and put it in the var of the main form.  then i moved it to the procedure (derived from embedform procedure i found in the forum) for opening the child form.

Code: [Select]
procedure TFormMain.MenuItemStatesClick(Sender: TObject);
var
  FormInPanel : TForm;
  Ctrl : tControl;
begin
  FormInPanel := TForm(TFormStates.NewInstance);
  FormInPanel.Create(Panel1);
  while FormInPanel.ControlCount > 0 do begin
    Ctrl:=FormInPanel.Controls[0];
    Ctrl.Parent:=Panel1;
  end;

//  OpenFormInPanel;
  FormInPanel.OnCloseHandler := @ChildIsDestroyedNotifier;
end;

When i compile the program i get:

unitmain.pas(108,15) Error: identifier idents no member "OnCloseHandler"

The main form is mostly an empty shell for the child forms.

Code: [Select]
uses
  Windows, Classes, SysUtils, FileUtil, LResources, Forms, Controls,
  Graphics, Dialogs, StdCtrls, Menus, ExtCtrls, UnitVendor2,
  UnitLibrary, UnitStates;

type

  { TFormMain }

  TFormMain = class(TForm)
    Label1: TLabel;
    MainMenu1: TMainMenu;
    MenuHelp: TMenuItem;
    MenuItemStates: TMenuItem;
    MenuItemVendors: TMenuItem;
    MenuItem2: TMenuItem;
    MenuItem3: TMenuItem;
    MenuItemExit: TMenuItem;
    MenuItemAbout: TMenuItem;
    MenuFile: TMenuItem;
    Panel1: TPanel;
    procedure FormCreate(Sender: TObject);
    procedure FormResize(Sender: TObject);
    procedure MenuItemStatesClick(Sender: TObject);
    procedure MenuItemVendorsClick(Sender: TObject);
    procedure MenuItemAboutClick(Sender: TObject);
    procedure MenuItemExitClick(Sender: TObject);
    procedure ChildIsDestroyedNotifier;
  private
//    procedure OpenFormInPanel;
  public
  end;

var
  FormMain: TFormMain;
//  FormInPanel : TForm;


I appreciate your help

eny

  • Hero Member
  • *****
  • Posts: 1665
Re: Close Form
« Reply #9 on: February 22, 2011, 10:28:57 am »
A slightly simpler solution, if you use simple embedded forms.
Only the main form has to do something:
1. Add a 'embedded form' close method to the main form.
2. Set the embedded's form OnClose handler to this close method.

Code: Pascal  [Select][+][-]
  1. procedure TfrmMain1.EmbeddedFormClose(Sender: TObject; var CloseAction: TCloseAction);
  2. begin
  3.   // Do all embedded form closing processig...
  4.   ShowMessage('Embedded form is closing...');
  5. end;
  6.  
  7. procedure TfrmMain.TFormMain.MenuItemStatesClick(Sender: TObject);
  8. var FormInPanel: TForm;
  9. begin
  10.   //...
  11.   FormInPanel.OnClose := @EmbeddedFormClose;
  12. end;
  13.  
All posts based on: Win11; stable Lazarus 4_4  (x64) 2026-02-12 (unless specified otherwise...)

Old Dog

  • New Member
  • *
  • Posts: 17
Re: Close Form
« Reply #10 on: February 27, 2011, 09:19:10 pm »
Thank you, it does what I want.

 

TinyPortal © 2005-2018