Accessing Variables and Calling Procedures

You need to be clear about the way that form-based applications use the interface and implementation sections in your units. The interface section is for declaring types, constants, variables and routines that you access from other files. Forms are accessed by the project file and need to be declared in the interface. Declare in the implementation section types, constants and variables that you only need to use within the same unit. Also put the code for all routines in the implementation section.

You should decide whether your own procedures and functions should be methods of the form or separate. This makes a difference to how they are defined and accessed. In our tutorial on object-oriented Pascal we showed how public methods can control access to private fields. You might decide to write your own classes to 'encapsulate' your data in this way. (In our experience few school students at present have the expertise and confidence to write object-oriented Pascal code for their coursework). Usually your own routines (such as for sorting and searching data) do not need to be methods of the form.

We see students struggling to debug advanced projects while they are experimenting with new techniques. We strongly recommend that you experiment with simple, well documented examples before introducing new types of code. We provide an example here of a relatively simple two-form application to demonstrate how to declare and use variables and procedures when they are part of a form and when they are separate. Note that each unit has the other unit in its uses section of the implementation.

The click event procedure of Form One runs two ShowMessage procedures before showing Form Two. The captions of the labels in Form Two take data from the first unit. The buttons run procedures in the first unit. The following screenshot shows both forms and the message dialogue shown when you press the left button of Form Two.

Program Access in action

Program Access in action

The essential code of the five files needed for program Access follows. The comments should help you to write your own code. If you want to run the program, you can download the code of the five files in form_access.zip

uOne.pas

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type
  TfrmOne = class(TForm)
    lblInstruction: TLabel;
    procedure FormClick(Sender: TObject);
    procedure MyFormProcedure;
  public
    MyFormVariable : string;
  end; 

var
  frmOne: TfrmOne;
  MyUnitVariable : string = 'Unit';

procedure MyUnitProcedure;

implementation

uses
  uTwo;
{$R *.lfm}
procedure MyUnitProcedure;
begin
  ShowMessage('Running unit procedure from Form One');
  //Procedure not part of form so needs frmOne. before component name
  frmOne.lblInstruction.Top := frmOne.lblInstruction.Top - 20;
end;

procedure TfrmOne.MyFormProcedure;
begin
  ShowMessage('Running form procedure from Form One');
  //Procedure is method of form so can name component without prefix frmOne.
  lblInstruction.Top:= lblInstruction.Top + 20;
end;

procedure TfrmOne.FormClick(Sender: TObject);
begin
  MyUnitProcedure;
  MyFormProcedure;
  MyFormVariable := 'Form';
  frmTwo.Show;
end;

end.
  

uOne.lfm

object frmOne: TfrmOne
  Left = 550
  Height = 85
  Top = 150
  Width = 330
  Caption = 'Form One'
  OnClick = FormClick
  object lblInstruction: TLabel
    Left = 8
    Height = 21
    Top = 40
    Width = 335
    Caption = 'Click here to run procedures and see Form Two'
    ParentColor = False
  end
end
  

uTwo.pas

unit uTwo;

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls;

type
  TfrmTwo = class(TForm)
    btnFormProcedure: TButton;
    btnUnitProcedure: TButton;
    lblUnitVariable: TLabel;
    lblFormVariable: TLabel;
    procedure btnFormProcedureClick(Sender: TObject);
    procedure btnUnitProcedureClick(Sender: TObject);
    procedure FormActivate(Sender: TObject);
  end; 

var
  frmTwo: TfrmTwo;

implementation
{$R *.lfm}
uses
  uOne;

//Accesses variables in another unit
procedure TfrmTwo.FormActivate(Sender: TObject);
begin
  //Prefix required for MyFormVariable
  lblFormVariable.Caption := 'Contents of form variable in uOne: ' + frmOne.MyFormVariable;

  //No prefix required for MyUnitVariable but prefix uOne. is accepted
  lblUnitVariable.Caption := 'Contents of unit variable in uOne: ' +  MyUnitVariable;
end;

//Calls procedure (method) in frmOne
procedure TfrmTwo.btnFormProcedureClick(Sender: TObject);
begin
  //Form prefix needed
  frmOne.MyFormProcedure;
end;

//Calls procedure in uOne
procedure TfrmTwo.btnUnitProcedureClick(Sender: TObject);
begin
  //Prefix not needed but prefix uOne. is accepted
  MyUnitProcedure;
end;

end.
        

uTwo.lfm

object frmTwo: TfrmTwo
  Left = 550
  Height = 85
  Top = 270
  Width = 330
  Caption = 'Form Two'
  OnActivate = FormActivate
  object lblFormVariable: TLabel
    Left = 0
    Height = 1
    Top = 10
    Width = 1
    ParentColor = False
  end
  object lblUnitVariable: TLabel
    Left = 0
    Height = 1
    Top = 30
    Width = 1
    ParentColor = False
  end
  object btnFormProcedure: TButton
    Left = 10
    Height = 25
    Top = 60
    Width = 158
    Caption = 'Procedure in frmOne'
    OnClick = btnFormProcedureClick
    TabOrder = 0
  end
  object btnUnitProcedure: TButton
    Left = 176
    Height = 25
    Top = 60
    Width = 131
    Caption = 'Procedure in uOne'
    OnClick = btnUnitProcedureClick
    TabOrder = 1
  end
end                      

Access.lpr

program Access;

uses
  Interfaces, Forms, uOne, uTwo;

begin
  Application.Initialize;
  Application.CreateForm(TfrmOne, frmOne);
  Application.CreateForm(TfrmTwo, frmTwo);
  Application.Run;
end.     
Programming - a skill for life!

Using widgets (such as list boxes, combo boxes, string grids, DBgrids, charts and maps) and drawing on the canvas