Solved

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

Posted on 2014-11-23
13
147 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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 27

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
 
LVL 27

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

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
How to implement a row column color change using Dev Express Quantum Grid in Delphi 3 77
Delphi 2 87
Firemonkey webbrowser scrollbars ? 1 65
Delphi, TImage, Png 2 51
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Finds all prime numbers in a range requested and places them in a public primes() array. I've demostrated a template size of 30 (2 * 3 * 5) but larger templates can be built such 210  (2 * 3 * 5 * 7) or 2310  (2 * 3 * 5 * 7 * 11). The larger templa…
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…

742 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