Solved

How do I close an fsStayOnTop child window from the parent ?

Posted on 2014-11-23
13
143 Views
Last Modified: 2014-12-07
I have an fsStayonTop child form and want to be able to close it from the parent form. How do i do it ?
0
Comment
Question by:ChLa
  • 6
  • 4
  • 2
  • +1
13 Comments
 
LVL 24

Expert Comment

by:jimyX
ID: 40461778
Is "ChildForm.Close" doesn't work?

Could you provide more details? What setup you have there?
0
 

Author Comment

by:ChLa
ID: 40462444
Hi,

I am using Delphi the latest RAD studio. While this is for a larger program I am working on, I am testing it on a super used for learning the basics of having a sizable child window, and this work is going on in Delphi 2010. I have named this child window Bobby, and declared Unit1 in uses. I find the same problems in the latest RAD studio, and in Delphi 2010.

I have tried many things. ChildForm.Close doesn't work, i get undeclared identifiers for ChildForm and Close. Here are other things I have tried, and the results:
Bobby.Close:  Compiles but I get an access violation when it is called.
TBobby.Close; I get This form of method call is only allowed for class methods.
MDIChildren[0].Close; Compiles but gets access violation error when it is called.
Unit1.Bobby.Close; Compiles but I get an access violation when it is called.
Unit1.Close; Unit1 does not have a member named Close.
Form1.Close; Undeclared identifiers Form1 and Close.
Form1.Bobby.Close; Undeclared identifiers.
0
 

Author Comment

by:ChLa
ID: 40462613
Here is the code from my main form of the small test project. Here you can see some of the things I have tried:

unit MAIN;

interface

uses Windows, SysUtils, Classes, Graphics, Forms, Controls, Menus,
  StdCtrls, Dialogs, Buttons, Messages, ExtCtrls, ComCtrls, StdActns,
  ActnList, ToolWin, ImgList;

type
  TMainForm = class(TForm)
    MainMenu1: TMainMenu;
    File1: TMenuItem;
    FileNewItem: TMenuItem;
    FileOpenItem: TMenuItem;
    FileCloseItem: TMenuItem;
    Window1: TMenuItem;
    Help1: TMenuItem;
    N1: TMenuItem;
    FileExitItem: TMenuItem;
    WindowCascadeItem: TMenuItem;
    WindowTileItem: TMenuItem;
    WindowArrangeItem: TMenuItem;
    HelpAboutItem: TMenuItem;
    OpenDialog: TOpenDialog;
    FileSaveItem: TMenuItem;
    FileSaveAsItem: TMenuItem;
    Edit1: TMenuItem;
    CutItem: TMenuItem;
    CopyItem: TMenuItem;
    PasteItem: TMenuItem;
    WindowMinimizeItem: TMenuItem;
    WindowTileItem2: TMenuItem;
    Panel1: TPanel;
    procedure FileNew1Execute(Sender: TObject);
    procedure FileOpen1Execute(Sender: TObject);
    procedure HelpAbout1Execute(Sender: TObject);
    procedure FileExit1Execute(Sender: TObject);
    procedure Panel1Click(Sender: TObject);
  private
    { Private declarations }
    procedure CreateMDIChild(const Name: string);
  public
    { Public declarations }
  end;

var
  MainForm: TMainForm;
  BobOpened: Integer = 0;

implementation

{$R *.dfm}

uses CHILDWIN, about, Unit1;

procedure TMainForm.CreateMDIChild(const Name: string);
var
  Child: TMDIChild;
begin
  { create a new MDI child window }
  Child := TMDIChild.Create(Application);
  Child.Caption := Name;
  if FileExists(Name) then Child.Memo1.Lines.LoadFromFile(Name);
end;

procedure TMainForm.FileNew1Execute(Sender: TObject);
begin
  CreateMDIChild('NONAME' + IntToStr(MDIChildCount + 1));
end;

procedure TMainForm.FileOpen1Execute(Sender: TObject);
begin
  if OpenDialog.Execute then
    CreateMDIChild(OpenDialog.FileName);
end;

procedure TMainForm.HelpAbout1Execute(Sender: TObject);
begin
  AboutBox.ShowModal;
end;

procedure TMainForm.Panel1Click(Sender: TObject);
begin
  if BobOpened = 0 then
    begin
      Unit1.TBobby.Create(self);
      Panel1.Caption := 'Close bobby';
      BobOpened := 1;
    end
  else
    begin
      //Form1.Bobby.Close;
      //unit1.Bobby.Close;
      //Unit1.TBobby.Close;
      //Form1.close;
      //Close Bobby
      //Bobby.Close;
      //MDIChildren[0].Close;
      //ChildForm.Close;
      //TBobby.Close;
      Panel1.Caption := 'Open bobby';
      BobOpened := 0;
    end;
end;

procedure TMainForm.FileExit1Execute(Sender: TObject);
begin
  Close;
end;

end.
0
 

Author Comment

by:ChLa
ID: 40462617
And here is the code from the child window (Bobby).

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, Spin;

type
  TBobby = class(TForm)
    Panel1: TPanel;
    Panel2: TPanel;
    Panel3: TPanel;
    Panel4: TPanel;
    procedure FormResize(Sender: TObject);
    procedure Panel3Click(Sender: TObject);

  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Bobby: TBobby;
  Iterations: Integer = 0;

implementation

{$R *.dfm}

uses main;


procedure TBobby.FormResize(Sender: TObject);
begin
  Panel2.Caption := IntToStr(Iterations);
  Iterations := Iterations + 1;
  if Iterations > 0 then
    Begin
      Panel1.Width := Trunc((Panel4.Width / 2) - 10);
      Panel2.Width := Trunc((Panel4.Width / 2) - 10);
      Panel2.Left := Trunc(Panel4.Width / 2);
    End;
end;

procedure TBobby.Panel3Click(Sender: TObject);
begin
  Close;
  MainForm.Panel1.Caption := 'Open Bobby';
  BobOpened := 0;
end;

end.
0
 
LVL 26

Accepted Solution

by:
Sinisa Vuk earned 250 total points
ID: 40463044
Uh... very wrong.....

1. declare class instance in TMainForm :
TMainForm =
....
public
    { Public declarations }
   MyBobby: TBobby;
end;

Open in new window

 

2. us it when create new child window:
procedure TMainForm.Panel1Click(Sender: TObject);
begin
  if not Assigned(MyBobby) then
  begin
     Application.CreateForm(TBobby, MyBobby);
     Panel1.Caption := 'Close bobby'; 
  end
 else
 begin
    MyBobby.Free; //this will close form and free it - this is what you need here
    MyBobby := nil;
 end;
end;

Open in new window


... click on panel will create new instance of TBobby or destroy old one. You don't need close here.
0
 

Author Comment

by:ChLa
ID: 40463408
I'm getting an undeclared identifier for TBobby. Do I need to declare it elsewhere before the public declaration ?
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 26

Expert Comment

by:Sinisa Vuk
ID: 40463546
move  Unit1 from lower uses to topmost.
0
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 40464482
that's not all that nice either
mind the circular reference

the main question you need to ask yourself
> how many stayonstop forms of that type will you have ? just the 1 > then manage that instance in the unit itself

having a parent is optional in that case
> unless you want the form to be embedded in another > but then it's not a stayontop form
0
 
LVL 37

Assisted Solution

by:Geert Gruwez
Geert Gruwez earned 250 total points
ID: 40464675
i boiled it down to a minimum on how to do this.

unit uMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;

type
  TForm1 = class(TForm)
    Panel1: TPanel;
    procedure Panel1Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

uses uBobby;

{$R *.dfm}

procedure TForm1.Panel1Click(Sender: TObject);
begin
  if IsBobOpen then
    CloseBobby
  else
    ShowBobby;
end;

end.

Open in new window



unit uBobby;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls;

type
  TBobby = class(TForm)
    Panel1: TPanel;
    procedure Panel1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
  public
  end;

var
  Bobby: TBobby;

procedure ShowBobby;
function IsBobOpen: Boolean;
procedure CloseBobby;

implementation

{$R *.dfm}

procedure ShowBobby;
begin
  if not IsBobOpen then
  begin
    Bobby := TBobby.Create(Application);
    Bobby.Show;
    Bobby.Update;
  end;
end;

function IsBobOpen: Boolean;
begin
  Result := Assigned(Bobby) and (Bobby <> nil);
end;

procedure CloseBobby;
begin
  FreeAndNil(Bobby);
end;

procedure TBobby.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
  Bobby := nil;
end;

procedure TBobby.Panel1Click(Sender: TObject);
begin
  Close;
end;

initialization
  Bobby := nil;
finalization
  CloseBobby;
end.

Open in new window

0
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 40464694
if you want to play with the caption of your main form panel
this is a way :

  TForm1 ... 

  protected
    procedure UpdateActions; override;
  end;

procedure TForm1.UpdateActions;
begin
  inherited;
  if (Panel1.Tag <> 2) <> IsBobOpen then
  begin
    if IsBobOpen then
    begin
      Panel1.Caption := 'Close bobby';
      Panel1.Tag := 1;
    end
      else
    begin
      Panel1.Caption := 'Open boby';
      Panel1.Tag := 2;
    end;
  end;
end;

Open in new window

0
 

Author Comment

by:ChLa
ID: 40464949
Moving the Unit1 declaration fixed it and it seems to work well.
Geert asks the question how many such children do I expect to have. My application will have two stayontop forms.
I will review the boiled down minimum from Geert. Thanks everyone.
0
 
LVL 37

Expert Comment

by:Geert Gruwez
ID: 40466256
two stayontopforms
> but 2 different types ...

TBobbyForm and TSomeOtherStayonTop
that's 1 of each

a stayontopform shouldn't be a child of the mdi form.
0
 

Author Closing Comment

by:ChLa
ID: 40485745
Thank you everyone.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
Internet Business Fax to Email Made Easy - With  eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, f…
Many functions in Excel can make decisions. The most simple of these is the IF function: it returns a value depending on whether a condition you describe is true or false. Once you get the hang of using the IF function, you will find it easier to us…

863 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now