Solved

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

Posted on 2014-11-23
13
141 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
Comment Utility
Is "ChildForm.Close" doesn't work?

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

Author Comment

by:ChLa
Comment Utility
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
Comment Utility
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
Comment Utility
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 25

Accepted Solution

by:
Sinisa Vuk earned 250 total points
Comment Utility
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
Comment Utility
I'm getting an undeclared identifier for TBobby. Do I need to declare it elsewhere before the public declaration ?
0
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
LVL 25

Expert Comment

by:Sinisa Vuk
Comment Utility
move  Unit1 from lower uses to topmost.
0
 
LVL 36

Expert Comment

by:Geert Gruwez
Comment Utility
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 36

Assisted Solution

by:Geert Gruwez
Geert Gruwez earned 250 total points
Comment Utility
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 36

Expert Comment

by:Geert Gruwez
Comment Utility
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
Comment Utility
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 36

Expert Comment

by:Geert Gruwez
Comment Utility
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
Comment Utility
Thank you everyone.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
This video discusses moving either the default database or any database to a new volume.
Access reports are powerful and flexible. Learn how to create a query and then a grouped report using the wizard. Modify the report design after the wizard is done to make it look better. There will be another video to explain how to put the final p…

771 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

11 Experts available now in Live!

Get 1:1 Help Now