Link to home
Avatar of ChLa
ChLaFlag for United States of America

asked on

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 ?
Avatar of jimyX
jimyX

Is "ChildForm.Close" doesn't work?

Could you provide more details? What setup you have there?
Avatar of ChLa

ASKER

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.
Avatar of ChLa

ASKER

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.
Avatar of ChLa

ASKER

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.
ASKER CERTIFIED SOLUTION
Avatar of Sinisa Vuk
Sinisa Vuk
Flag of Croatia image

Blurred text
THIS SOLUTION IS ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
Avatar of ChLa

ASKER

I'm getting an undeclared identifier for TBobby. Do I need to declare it elsewhere before the public declaration ?
move  Unit1 from lower uses to topmost.
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
SOLUTION
THIS SOLUTION IS ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
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

Avatar of ChLa

ASKER

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.
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.
Avatar of ChLa

ASKER

Thank you everyone.