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

I have an fsStayonTop child form and want to be able to close it from the parent form. How do i do it ?
ChLaAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jimyXCommented:
Is "ChildForm.Close" doesn't work?

Could you provide more details? What setup you have there?
0
ChLaAuthor Commented:
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
ChLaAuthor Commented:
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
Learn Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

ChLaAuthor Commented:
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
Sinisa VukSoftware architectCommented:
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
ChLaAuthor Commented:
I'm getting an undeclared identifier for TBobby. Do I need to declare it elsewhere before the public declaration ?
0
Sinisa VukSoftware architectCommented:
move  Unit1 from lower uses to topmost.
0
Geert GOracle dbaCommented:
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
Geert GOracle dbaCommented:
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
Geert GOracle dbaCommented:
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
ChLaAuthor Commented:
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
Geert GOracle dbaCommented:
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
ChLaAuthor Commented:
Thank you everyone.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.