rwb
rwb

Reputation: 11

Delphi - How to access a form from a childwindow in a mdi-application

I have an MDI programm with a child window which contains a TMemo and a button, there is also another Form1 in the application. Clicking the button:

Unit1.Form1.Parent:=Form1;
Unit1.Form1.Show;

On Form1 is also a button:

????.(FindComponent('dataMm') as TMemo).lines.append('hallo child');

My question is: what is the right syntax to replace the ???? to access the TMemo on the childform.

PS.: the TMainForm has the following procedure:

Procedure TMainForm.CreateMDIChild(const Name: string);
var
  Child: TMDIChild;
begin
  Child := TMDIChild.Create(Application);
  MyChild:=Child;
end;

where MyChild is declared in the public section as

var MyChild: TForm;

Thanks for your time and attention Regards

Upvotes: 1

Views: 920

Answers (1)

Tom Brunberg
Tom Brunberg

Reputation: 21033

At the time of writing this answer, you have not yet responded to my comment where I requested some clarifications, but I believe I understand your problem.

So here is the essens of the main form:

unit UMain;

uses
  ..., UChild, ...
    
type
  TMDIMainForm = class(TForm)
    MainMenu1: TMainMenu;
    CreateChild1: TMenuItem;
    ShowForm11: TMenuItem;
    ...
  public
    MyChild: TMDIChild;

As you usually have many instances of a child form, you need to use a list or array instead of the MyChild variable, but this is what you had defined.

And the implementation of those menu items, as well as the CreateMDIChild method:

procedure TMDIMainForm.CreateChild1Click(Sender: TObject);
begin
  CreateMDIChild('TheOneAndOnly');
end;

procedure TMDIMainForm.ShowForm11Click(Sender: TObject);
begin
  Form1.Show;
end;

procedure TMDIMainForm.CreateMDIChild(const name: string);
//var
//  Child: TMDIChild;  no need for this temporary variable
begin
  MyChild := TMDIChild.Create(Application);
  MyChild.Parent := self;
  MyChild.Visible := True;
//  MyChild:=Child;
end;

The TMDIChild class is as simple as:

unit UChild;

type
  TMDIChild = class(TForm)
    dataMm: TMemo;
  end;

as it only holds the memo (for the purpose of this discussion).

Finally the TForm1 class:

unit UForm1;

interface
type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;

implementation

uses UMain, UChild;

procedure TForm1.Button1Click(Sender: TObject);
begin
  MDIMainForm.MyChild.dataMm.Lines.Add('hello child!')
end;

I guess we have now arrived to your actual question, how to address the memo in the MyChild form.

So, note that you need to add the uses UMain, UChild; clause to refer to those units. This uses clause must be in the implementation part. If it would be in the interfacepart, it would create a circular reference, which is forbidden.

Now you can refer to the memo in the child form which has it's reference in the main form.


Edit

After you clarified in a comment: ("Actually the Button to make visible the Form1 is on the child, and this can happen on any child. Than on Form1 a button activates : dataMm.Lines.Add('hello child!'). I need a reference or connection to this currently active child", you can do as follows:

Add to the TForm1 type, a new private field to hold the MDIChild reference, and a new method, in which you can pass the reference of the calling MDIChild, e.g.

TForm1 = class(TForm)
...
private
  CurrentMDIChild: TMDIChild;
public
  procedure DoActivate(Sender: TMDIChild);

The implementation of DoActivate() becomes:

procedure TForm1.DoActivate(Sender: TMDIChild);
begin
  if (Sender is TMDIChild) then
  begin
    CurrentMDIChild := Sender;
    Show;
  end;
end;

The TMDIChild.Button1Click becomes e.g.

procedure TMDIChild.Button1Click(Sender: TObject);
begin
  Form1.DoActivate(self); 
end;

Upvotes: 1

Related Questions