Bookstore

Recent

Author Topic: [SOLVED] How to know the form that launched another one?  (Read 1591 times)

kinlion

  • Jr. Member
  • **
  • Posts: 55
  • I Love Lazarus
Re: How to know the form that launched another one?
« Reply #15 on: February 27, 2020, 07:11:33 am »
I will try to do this:

1. Create a global variable in the modal form, like var CallerForm: TForm;
2. Any (main)form must set the ModalForm.CallerForm := self; before calling the modal form
3. On the modal form you can use CallerForm.Color := something;

If you prefer OOP style, for #1 create a public method (you can name it) SetCaller to store the caller form.

I agree to OOP style.

For simple, one can just assign a form's owner to the caller when creating. Like this:
Code: Pascal  [Select]
  1. procedure TFormA.OnButtonClick(Sender: TObject);
  2. begin
  3.     FormB := TFormB.Create(Self);
  4.     FormB.ShowModal;
  5.     FormB.Free;
  6. end;
  7.  
  8. procedure TFormB.OnButtonClick(Sender: TObject);
  9. begin
  10.     (Owner as TFormA).Color := clXXX;
  11.     // or
  12.     // (Owner as TForm).Color := clXXX; { more general but can't access properties of TFormA }
  13. end;
  14.  
  15. FormA  := TFormA.Create(nil);
  16.  
  17.  

More convenient, you even don't need to free FormB. Since FormB's owner is FormA, FormB will be freed during FormA is freeing. But it's better to free anything that you created.

Generally, Parent indicates on which space to show, meanwhile Owner indicates who is responsible to manage it's life time.
« Last Edit: February 27, 2020, 07:14:31 am by kinlion »
Lazarus 1.8.4 / FPC 3.0.4 / SVN 57972
On Win10 X64, have to compile for Win32

GetMem

  • Hero Member
  • *****
  • Posts: 3630
Re: How to know the form that launched another one?
« Reply #16 on: February 27, 2020, 07:14:39 am »
@Handoko

Actually none of the suggested(OOP) methods will work. Looking at his attached project, the secondary forms are auto-created, which means:
- the owner is TApplication
- parent is nil
If he creates the forms dynamically, everything becomes trivial:
Code: Pascal  [Select]
  1.   ModalForm := TModalForm .Create(Self); //Self is the main form
  2.   try
  3.     ModalForm.ShowModal;
  4.   finally
  5.     ModalForm.Free
  6.   end;
  7.  
  8. //Then on the modal form, put a button and create an OnClick event:
  9.  
  10. procedure TForm2.Button1Click(Sender: TObject);
  11. begin
  12.   Self.Color := TForm(Self.Owner).Color
  13. end;
  14.  
  15.  
« Last Edit: February 27, 2020, 08:50:20 am by GetMem »

egsuh

  • Sr. Member
  • ****
  • Posts: 322
Re: How to know the form that launched another one?
« Reply #17 on: February 27, 2020, 08:28:14 am »
Well I don't see any problem with Handoko's approach.. but I'd put a variable within the public section rather than using global variable.  For example,

Code: Pascal  [Select]
  1. TForm2 = class (TForm)
  2. public
  3.      ParentForm: TForm; // or TComponent
  4. end;
  5.  
  6.  
  7. TForm1.Button1Click(Sender: TObject)
  8. begin
  9.      Form2.ParentForm := self;
  10.      Form2.ShowModal;
  11. end;

In this way, many other forms can call Form2, and Form2 knows which form called it.
« Last Edit: February 27, 2020, 08:30:40 am by egsuh »

BrunoK

  • Full Member
  • ***
  • Posts: 228
  • Retired programmer
Re: How to know the form that launched another one?
« Reply #18 on: February 27, 2020, 10:51:15 am »
In attachment, a hopefully working project that might do what the OP asks.

MarkMLl

  • Hero Member
  • *****
  • Posts: 711
Re: How to know the form that launched another one?
« Reply #19 on: February 27, 2020, 11:52:17 am »
Well I don't see any problem with Handoko's approach.. but I'd put a variable within the public section rather than using global variable.

Which is, after all, what it's there for. I think there would be a good argument for making global variables to units other than the privileged form creator, or to move form variables into the implementation part and expose them via a function.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.

lucamar

  • Hero Member
  • *****
  • Posts: 2588
Re: How to know the form that launched another one?
« Reply #20 on: February 27, 2020, 01:19:16 pm »
Actually none of the suggested(OOP) methods will work. Looking at his attached project, the secondary forms are auto-created, which means:
- the owner is TApplication
- parent is nil

Which is, among other reasons, why I insisted that he needs to pass (and store) the caller through an "Execute" call (similar to what the common dialogs do). That is almost the only way to know unequivocally which form called, and more so if the code somehow "hides" any other method of showing the ... let's call it "dialog", whether Show, ShowModal or whatever else.

I had a similar problem, though for other reasons, with a common form of mine (basically an "About" dialog which also shows debugging info on demand, hence the problem), and the solution was almost exactly as I have outlined before.

Incidentaly, a terminology question: the form which the OP wants to know about is neither the owner or the parent; it's the caller form. Talking about owners and parents kind of obscures the issue at hand. At least, if I understand the question correctly ;)
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.6/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

GetMem

  • Hero Member
  • *****
  • Posts: 3630
Re: How to know the form that launched another one?
« Reply #21 on: February 27, 2020, 02:07:30 pm »
@lucamar

I agree, from OOP point of view passing the caller is the best solution.
I re-read OP's original post, where he mentions that the ModalForm is always called from main form. If this is true, the solution is ridiculously simple  :D :
Code: Pascal  [Select]
  1.  ModalForm.Color := Application.Mainform.Color
« Last Edit: February 27, 2020, 02:16:55 pm by GetMem »

lucamar

  • Hero Member
  • *****
  • Posts: 2588
Re: How to know the form that launched another one?
« Reply #22 on: February 27, 2020, 06:25:16 pm »
I re-read OP's original post, where he mentions that the ModalForm is always called from main form. If this is true, the solution is ridiculously simple  :D :
Code: Pascal  [Select]
  1.  ModalForm.Color := Application.Mainform.Color

Yeah, at a minimum that would be a nice default in case the caller is unknown :)
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.6/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

kupferstecher

  • Sr. Member
  • ****
  • Posts: 365
Re: How to know the form that launched another one?
« Reply #23 on: February 28, 2020, 12:48:28 am »
Any way, would the component.property method be an OOP rule or principle violation? I've been struggling with this doubt for a time.
In my opinion, if you  r e a d  the property only, it is not a violation. But if you set it, e.g. change the main forms color from within an other unit, it would not be very clear later where this happens. Thats why I suggested the callback. But only for the case of writing.

Anyways, from OOP point of view properties are the correct way to access class fields, as they can implement getters/setters as well as the direct field access.

winni

  • Hero Member
  • *****
  • Posts: 1138
Re: How to know the form that launched another one?
« Reply #24 on: February 28, 2020, 01:11:14 am »
Hi!

No, this is not a problem. If you use the recursive uses as shown above, it is always possible that you change from unit2/Form2 the properties of Form1. No hassle.

Winni

egsuh

  • Sr. Member
  • ****
  • Posts: 322
Re: How to know the form that launched another one?
« Reply #25 on: February 28, 2020, 04:20:01 am »
Quote
If you use the recursive uses as shown above, it is always possible that you change from unit2/Form2 the properties of Form1.

Problem is that he wants to share unit2/form2 for other applications as well, whose caller form may be in unit3, unit4, etc. 

Quote
the ModalForm is always called from main form

Currently ModalForm is called only by main form. But later, other forms than application.mainform may call the ModalForm.

In delphi, TCustomForm.ShowModal is defined as follow.

Code: Pascal  [Select]
  1. function ShowModal: Integer; virtual;

So I think we may re-define TForm2.ShowModal.
Code: Pascal  [Select]
  1. unit Unit2;
  2. type
  3.    TForm2 = class(TForm)
  4.       Button1: TButton;
  5.       procedure Button1Click(Sender: TObject);
  6.    private
  7.       CallerForm: TForm;
  8.    public
  9.       function ShowModal (caller: TForm) : integer;
  10.    end;
  11.  
  12. var
  13.    Form2: TForm2;
  14.  
  15. implementation
  16.  
  17. procedure TForm2.Button1Click(Sender: TObject);
  18. begin
  19.    if CallerForm <> nil then color := CallerForm.Color;
  20. end;
  21.  
  22. function TForm2.ShowModal(caller: TForm): integer;
  23. begin
  24.    CallerForm := caller;
  25.    Result := inherited ShowModal;
  26. end;
  27.  
  28. //// ---- And in calling units ------------------------
  29.  
  30. procedure TForm1.Button1Click(Sender: TObject);
  31. begin
  32.    Form2.ShowModal(Self);
  33. end;
  34.  


egsuh

  • Sr. Member
  • ****
  • Posts: 322
Re: How to know the form that launched another one?
« Reply #26 on: February 28, 2020, 04:30:28 am »
Also ModalForms should close when its ModalResult is assigned with other values than 0 (mrNone).
So I tested followings, which works as expected.

Code: Pascal  [Select]
  1. procedure TForm2.Button2Click(Sender: TObject);
  2. begin
  3.    ModalResult := mrOK;   // This closes Form2.
  4. end;
  5.  
  6. procedure TForm1.Button1Click(Sender: TObject);
  7. var
  8.    i: integer;
  9. begin
  10.    i :=  Form2.ShowModal(Self);
  11.    ShowMessage(IntToStr(i));   // displays 1 if I press Button2, and 2 if I close Form2 by clicking border icon.  
  12. end;
  13.  

lucamar

  • Hero Member
  • *****
  • Posts: 2588
Re: How to know the form that launched another one?
« Reply #27 on: February 28, 2020, 03:48:56 pm »
Also ModalForms should close when its ModalResult is assigned with other values than 0 (mrNone).
So I tested followings, which works as expected.

Code: Pascal  [Select]
  1. procedure TForm2.Button2Click(Sender: TObject);
  2. begin
  3.    ModalResult := mrOK;   // This closes Form2.
  4. end;

Note that you don't need to set it in an event handler; all buttons have a ModalResult property which works automagically to set the form's ModalResult (which in turn makes it close if modally shown) when clicked
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus 2.0.6/FPC 3.0.4 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

Raul_ES

  • Full Member
  • ***
  • Posts: 114
  • My interests: Healthcare & Computers
    • My Linkedin Profile, you can add me to stay in contact.
Re: How to know the form that launched another one?
« Reply #28 on: March 04, 2020, 06:12:06 pm »
Thank you all for your help and comments. This is one of the very reasons I love this forum.

I actually used the solution of overloading the ShowModal method with ShowModal(Caller: TForm). The example provided by egsuh, it's clear, easy to follow and understand.

I modified it to:
Code: Pascal  [Select]
  1. function ShowModal(caller: TForm) : integer; overload;

just to decouple it a little more from any caller unit, so that will not break the code when using ShowModal() instead of ShowModal(Self).

regards
Pharmacy + Chemistry + Biology + Healthcare + Computing

If you have any interest or project related with these areas feel free to contact me!

Raul_ES

  • Full Member
  • ***
  • Posts: 114
  • My interests: Healthcare & Computers
    • My Linkedin Profile, you can add me to stay in contact.
Re: How to know the form that launched another one?
« Reply #29 on: March 04, 2020, 06:21:48 pm »
Incidentaly, a terminology question: the form which the OP wants to know about is neither the owner or the parent; it's the caller form. Talking about owners and parents kind of obscures the issue at hand. At least, if I understand the question correctly ;)

I have some confusion with all these terms, sender, caller, owner, parent, child.... I need more reading and practice  ;) Thanks!
Pharmacy + Chemistry + Biology + Healthcare + Computing

If you have any interest or project related with these areas feel free to contact me!