4
votes

I want to access a main form variable from a class that is called from the main from. Something like this:

Unit1:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,Unit2, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
  public
  end;
var
  Form1: TForm1;
  Chiled:TChiled;
const
 Variable = 'dsadas';
implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  Chiled.ShowMainFormVariable;
end;

end.

Unit2:

unit Unit2;

interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

  type
  TChiled = class
  private
  public
    procedure ShowMainFormVariable;
  end;
var
  Form1: TForm1;
implementation

procedure TChiled.ShowMainFormVariable;
begin
  ShowMessage(Form1.Variable);
end;
end.

if in Unit2 i add to uses Unit1 an circular errors pops up.

How to make the Unit1 to be GLOBAL?

4
Name "Variable" for a constant, that's simply... genious.NGLN

4 Answers

6
votes

As other answers tell, you should use one of the units in implementation section.

Suppose you chose in 'unit2' you'd use 'unit1' in implementation. then you need to devise a mechanism to tell the 'TChiled' how to access 'Form1'. That's because since you haven't used 'unit1' in interface section of 'unit2', you cannot declare the 'Form1:TForm1' variable in interface section. Below is just one possible solution:

unit2

type
  TChiled = class
  private
    FForm1: TForm;
  public
    procedure ShowMainFormVariable;
    property Form1: TForm write FForm1;
  end;

implementation

uses
  unit1;

procedure TChild.ShowMainFormVariable;
begin
  ShowMessage((FForm1 as TForm1).Variable);
end;

then in unit1 you can set the Form1 property of TChiled before calling TChiled's method:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Chiled.Form1 := Self;
  Chiled.ShowMainFormVariable;
end;
3
votes

the simplest solution is to add Unit1 to a uses clause inside Unit2's implementation section as this gets around the circular reference.

However I'd suggest that this design is flawed. It is hard to see what you are trying to achieve with the sample code so it is difficult to offer any real advice.

3
votes

Well, the simple naive answer is that you should add Unit1 to the uses clause of the implementation section of Unit2:

unit Unit2;
......
implementation

uses
  Unit1;
.....

You can't add it to the uses clause in the interface section of Unit2 since that would create a circular reference at the interface section. In order words, the interface of Unit1 would uses Unit2, and the interface of Unit2 would use Unit1. The language does not allow that. The common solution is to use one of the units at the implementation level.


Having said that, your code is rather confused and fails in many other ways. Your problems run deeper than the circular reference. For example, what do you mean by Form1.Variable? The constant Variable is not a member of TForm1. You declare two global variables named Form1 of type TForm1. Why do you do that?

Also, you have spelled child incorrectly.

1
votes

I generally create a Data Module (or any type of non-visual container) to share global variables. This way both units can use the variable without a circular reference.