Solved

How do you pass values between forms ?

Posted on 2001-06-27
23
236 Views
Last Modified: 2010-04-06
I have written an app that basically has many forms, one of which is a main menu.

Depending on users access rights, I need to open a form with the database components as either READ ONLY or READ/WRITE. ie. Add,Delete, Edit etc. options/buttons are unavailable or available depending on users rights.

From the main menu, I access the user's login id, and check their access rights, if they are able to access the form, it opens with the appropriate buttons enabled/disabled.

My problem is how do I pass a value to the form, and then where do add the code so that when the form opens, it uses this value to enable/disable the buttons.

I tried the following code which worked one minute, I believe it was when the code was used with the OnCreate Event of the Form, but doesn't work when attached to the OnShow Event.

Basically

Main Menu Code - Calls Form1
-----------------------------

const
 Access_FA = 1;  // Full Access
 Access_RW = 2;  // Read Write
 Access_RO = 3;  // Read Only
 Access_NO = 99; // No Access

Form1.Tag:=axsType; // axsType is assigned a Constant Value
Form1.Show;

Form1 Code
--------------------------
procedure TForm1.FormShow(Sender: TObject);
var i: Integer;
    IsOK: Boolean;
begin
  i:=Form1.Tag;
  IsOK:=False;
  case i of
    1,2:IsOK:=True;  // If true Enable Buttons
  else IsOK:=False;  // If False Disable Buttons
  end;

  btnInsert1.Enabled:=IsOK;
  btnDuplicate1.Enabled:=IsOK;
  btnEdit1.Enabled:=IsOK;
  btnDelete1.Enabled:=IsOK;
  btnCancel1.Enabled:=IsOK;
  btnPost1.Enabled:=IsOK;
end;

Any help would be appreciated.

Thanks
pjelias
0
Comment
Question by:pjelias
  • 7
  • 6
  • 5
  • +3
23 Comments
 
LVL 22

Expert Comment

by:mnasman
ID: 6233935
try to put ur code in the OnActivate event
0
 
LVL 6

Expert Comment

by:zebada
ID: 6233968
Mnasman is correct, use the OnActivate event.
You should probably also create properties for the form and set those properties (instead of .tag) prior to your form.show or form.showmodal statements.

i.e.

  TfMyForm = class(TForm)
    // Controls on form defined here...
  private
    FAccessRights: integer;

  public
    property AccessRights: integer read FAccessRights write FAccessRights;
  end;

You would invoke it like this:

  MyForm.AccessRights := 1234;
  MyForm.Show;

Its just a little mor elegant than using the tag property - you can also set up as many properties as you want - all different datatypes.
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6234034
you can also use a unit for this

like

unit globals;
interface

const
Access_FA = 1;  // Full Access
Access_RW = 2;  // Read Write
Access_RO = 3;  // Read Only
Access_NO = 99; // No Access

var
  AccessRights : Integer = Access_NO; //ADefaultValue
  //maybe more globals
implementation

end.

and add this  to the uses clause to your formunits so that
each formunit can read and set this values

meikl ;-)
0
 
LVL 3

Accepted Solution

by:
Stefaan earned 150 total points
ID: 6234050
Hi,

Do you create your forms at Run-Time ? Using something like Form1 := TForm1.Create( Self ) ? If so, then a much better alternative would be a combination of a property and a custom constructor.  I have set up a little sample in which my form looks like this :

unit Unit1;

interface

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

type
  { The different types of Access Right }
  TAccessRight = ( arRead, arWrite, arAdd, arRemove );
  { Will be used to hold any combination of TAccessRight }
  TAccessRights = set of TAccessRight;

  TForm1 = class(TForm)
    btnEdit: TButton;
    btnPost: TButton;
    btnCancel: TButton;
    btnDelete: TButton;
    btnDuplicate: TButton;
    btnInsert: TButton;
  private
    FAccessRights: TAccessRights;
    procedure SetAccessRights(const Value: TAccessRights);
    { Private declarations }
  protected
    procedure DisableButtons;
  public
    { Public declarations }
    Constructor Create( AOwner : TComponent; ARights : TAccessRights ); reintroduce; overload;
    property AccessRights : TAccessRights read FAccessRights write SetAccessRights;
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

{ TForm1 }

{*****************************************************************************
  Name           : TForm1.Create
  Author         : Lesage Stefaan
  Arguments      : AOwner  - The owner of the Form.
                   ARights - The access rights which should be used to enable
                             or disable some actions / buttons
  Return Values  : None
  Exceptions     : None
  Description    :
  History        :

  Date         By                   Description
  ----         --                   -----------
  28/06/2001   Lesage Stefaan       Initial creation of the Procedure.
 *****************************************************************************}

constructor TForm1.Create(AOwner: TComponent; ARights: TAccessRights);
begin
  Inherited Create( AOwner );
  AccessRights := ARights;
end;

{*****************************************************************************
  Name           : TForm1.DisableButtons
  Author         : Lesage Stefaan
  Arguments      : None
  Return Values  : None
  Exceptions     : None
  Description    : This procedure will be used to disable all buttons / actions
  History        :

  Date         By                   Description
  ----         --                   -----------
  28/06/2001   Lesage Stefaan       Initial creation of the Procedure.
 *****************************************************************************}

procedure TForm1.DisableButtons;
begin
  btnEdit.Enabled := False;
  btnPost.Enabled := False;
  btnCancel.Enabled := False;
  btnDelete.Enabled := False;
  btnDuplicate.Enabled := False;
  btnInsert.Enabled := False;
end;

{*****************************************************************************
  Name           : TForm1.SetAccessRights
  Author         : Lesage Stefaan
  Arguments      : Value - The new value for the AccessRights property.
  Return Values  : None
  Exceptions     : None
  Description    : Property Setter for the AccessRights property.
  History        :

  Date         By                   Description
  ----         --                   -----------
  28/06/2001   Lesage Stefaan       Initial creation of the Procedure.
 *****************************************************************************}

procedure TForm1.SetAccessRights(const Value: TAccessRights);
begin
  if Value <> FAccessRights then
  begin
    FAccessRights := Value;

    { First Disable all Buttons and then Reenable them according to the
      AccessRights }
    DisableButtons;

    { Here you should add the code which enables / disables different
      actions / components depending on the AccessRights }

    if arRead in FAccessRights then
    begin
      { Enable Read things }
    end;
    if arWrite in FAccessRights then
    begin
      { Enable Write things }
      btnEdit.Enabled := True;
      btnPost.Enabled := True;
      btnCancel.Enabled := True;
    end;
    if arAdd in FAccessRights then
    begin
      { Enable Insert things }
      btnInsert.Enabled := True;
      btnDuplicate.Enabled := True;
      btnPost.Enabled := True;
      btnCancel.Enabled := True;
     end;
    if arRemove in FAccessRights then
    begin
      { Enable Delete things }
      btnDelete.Enabled := True;
    end;
  end;
end;

end.


Now when I initially create the form, I can pass the accessrights to the form through its constructor :


MyForm := TForm1.Create( Self, [ arRead, arWrite, arAdd, arRemove ] ); // Full Access

or

MyForm := TForm1.Create( Self, [ arRead, arWrite ] ); // Read Write without add / remove Access

or

MyForm := TForm1.Create( Self, [ arRead ] ); // Read Access

or any combination of the for types.

If the form is already there and e.g. another user with other rights logs on, I can modify the property and the buttons will be enabled / disabled :

MyForm.AccessRights := [ arRead, arWrite, arAdd ];

Quite simple in fact.

If you have any questions feel free to post a comment.


best regards,


Stefaan
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6234176
at least the more elegant method, stefaan :-))
0
 
LVL 2

Expert Comment

by:Felixin
ID: 6234320
And to complete stefaan work I would add rewriting the Show and ShowModal methods of the form so that I would make something like

if bot Assigned (MyWindow) then
begin
  MyWindow := TMyWindow.Create (Self, Rights);
  MyWindow.ShowModal;
end
else
  MyWindow.ShowModal (Rights);

It would also serve to change the rights on the fly

At some point
 
  ...
  PerformUsingLogin;
  ....
  ....
  MyWindow.ShowModal (NewRights);


I mean, sometimes, in my applications I don't need to shutdown everything to make a new login. I just give the opportunity to re-login and everything will work without having to destroy and re-create every single window.

Felixin  
0
 
LVL 3

Expert Comment

by:Stefaan
ID: 6234324
Hi Kretzschmar,

ehm, what exactly do you mean ? Did I do something wrong ?

Best regards,


Stefaan
0
 
LVL 3

Expert Comment

by:Stefaan
ID: 6234334
Felixin,

I think rewriting the Show and ShowModal method is not necessary.  Using the following code :

With TForm1.Create( Self, [ arRead, arWrite ] ) do
begin
  ShowModal;
  Free;
end;

will do exactly what you want without rewriting the ShowModal method.

Best regards,


Stefaan
0
 
LVL 2

Expert Comment

by:Felixin
ID: 6234391
What should I do if I don't want to create the window anytime I want to use the form.

I was suggesting a way to dinamically change the rights when the window is already created.

I use to do it like this in order to speed up (how much I don't know) the form showing.

Yes, I agree that it does the same, it's only a different way to make it. Choosing one or another depends on how you thought your application, or how you like it more.

Don't you agree?.

Felixin
0
 
LVL 3

Expert Comment

by:Stefaan
ID: 6234434
Felixin,

If you do not want to create the window each time you want to use it, you can set the AccessRights property.  You have to create the form once, and afterwards simply updating the AccessRights property will do the trick.

When the window is already created you can simply modify the AccessRights property and the property setter will enable / disable the buttons according to the rights.

So dynamically modifying the AccessRights is perfectly possible, thus rewriting the Show and ShowModal methods isn't necessary.

Best regards,


Stefaan
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 6234435
>ehm, what exactly do you mean ? Did I do something wrong ?
oh no, you didn't stefaan, its more meant like a compliment->good work :-)
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 2

Expert Comment

by:Felixin
ID: 6234453
My argument is based only on personal preferences. I like better passing parameters than setting properties at run time. That's it, no more.

I'm with kretzschmar, yours is a good work.

I didn't mean to undervaluate your comment.

I, if you agree, stop here posting comments to not full up this question.

OK?

Felixin
0
 
LVL 3

Expert Comment

by:Stefaan
ID: 6234478
Felixin,

Well I know you didnt want to underevaluate my work ;-) But IMHO it is better to use the OO approach by setting the properties than by passing variables.  When you pass variables there is no way you can directly react on the passed variables ( or you should do it with a method ), but with properties it is perfectly possible to write a property setter which will handle the enabling / disabling of certain buttons or other components.

It is indeed some kind of personal preferences, but as we are given a very good OO tool ( Delphi ) why shouldn't we use the OO features of it.  That's exactly what makes us different to VB developers ;-)

Best regards,


Stefaan
0
 
LVL 2

Expert Comment

by:Felixin
ID: 6234505
My argument is based only on personal preferences. I like better passing parameters than setting properties at run time. That's it, no more.

I'm with kretzschmar, yours is a good work.

I didn't mean to undervaluate your comment.

I, if you agree, stop here posting comments to not full up this question.

OK?

Felixin
0
 
LVL 2

Expert Comment

by:Felixin
ID: 6234522
I recognize that, sometimes, I also use the settings of properties to perform some tasks.

Perhaps OO is not so inside of me as I thought, is it? :-)

(Sorry for the double posting)
0
 

Author Comment

by:pjelias
ID: 6236280
No, I do not create the forms at runtime.

Is it better to create the forms at runtime ?

I know this should be another question, but are there any benefits with creating Forms at Runtime ?

I have actually created an MDI application which did create forms at runtime, which was a bit difficult (haven't created one since), and have not looked at MDI since. I thought that Creating Forms would be more associated with MDI apps.

Regards
pjelias


0
 

Author Comment

by:pjelias
ID: 6236295
I have tried a couple of things mentioned, and a problem that I am getting is the values that are being returned, are not the ones I am expecting.

eg. When I run the App with Access_FA=1 I get values ranging from 33 to 1451423 (not the correct value but similar), which are not even close to the constants I have assigned.

Could these Constants be used elsewhere ?
0
 

Author Comment

by:pjelias
ID: 6236312
Stefaan,

in one of your posts you wrote the following

"If the form is already there and e.g. another user with other rights logs on, I can modify the property
and the buttons will be enabled / disabled :"

The system is obviously a multiuser app, will this have any impact on whether you create a form at runtime or not?

pjelias
0
 

Author Comment

by:pjelias
ID: 6236394
Stefaan,

I am trying your suggestion - can this code be put into a form and used, and then created at runtime ?

I have tried to create a Form with the code in it, and then used this to create (inherit) new forms, therefore am trying to use as a template.

When I create the new form based on the original, all the code that was written in it, has disappeared.

Am I doing the write thing ?
Do I have to add this code to every form I create ?

The forms I am creating can be quite complicated with upto 4 Master/Child tables linked, and multiple lookup tables, also upto 30 Forms will be created.

I would hate to have to write this code 30 times.
0
 

Author Comment

by:pjelias
ID: 6236879
Stefaan,

Tried the code you suggested which works well.

I also tried the following code you suggested which does not work. The Form flashes very briefly, and disappears.

//******************
With TForm1.Create( Self, [ arRead, arWrite ] ) do
begin
 ShowModal;
 Free;     // ASSUME THIS IS THE PROBLEM
end;

Otherwise the code is excellent.

A question by using the Free, I am assuming you are freeing resources associated with the form.

With the MDI apps I wrote, I was advised to use the following in the Forms OnClose event

  Action:=caFree;

Should/Could this be used on my forms OnClose event to free allocated memory ?

Also, the method/code you have suggested Stefaan, gets rid of the problems associated with using constants, therefore please ignore.

Ignore my previous posts, except the following

Date: 06/28/2001 04:51PM PST
Date: 06/28/2001 05:48PM PST

Could you please provide answers/suggestions if possible, especially about creating a "Template" Form that can be used.

I suppose I could create a Blank Form with the Basics, and use the File|Saves as option a few times to create copies ??

All help is greatly appreciated.

Regards
pjelias
0
 
LVL 3

Expert Comment

by:Stefaan
ID: 6237134
Hi,

Well you should use the form I supplied as a template to get the best results.  It is perfectly normal that if you inherit a new form from the template for that the code will not be in the new inherited form.  That is just what inheritance is about.  The code stays in the base form but the descendant forms will have the same functionality and properties without rewriting all the code.

So if you use the form supplied, you can inherit all your forms from that template and all will have the functionality and properties of the base form without having to rewrite the code everytime.


The showmodal sample i gave was to show the form modally from another form.  I tried it here with a sample application and it works perfectly well without flashing.

For the MDI Applications it is best to set the caFree in the OnClose event of the form, but sometimes you just want to show the form modally and wait till the user closes the form before you continue with the application and then you can use the code I supplied.  I must say that with forms it is better to use the Release method instead of the Free method, so it should look like this.

{ in form 2 I will create an instance of form1 and show }
{ it modally }

procedure TForm2.btnButton1Click(Sender: TObject);
begin
  with TForm1.Create( Self, [ arRead, arWrite ] ) do
  begin
    ShowModal;
    Free;
  end;
end;

Well, I would be very happy to help you with the template forms and things like that.  Form templates and Visual Form Inheritance are very powerfull things, and easy to use if you know how ;-)

So I am willing to give you some more advice / hints and tips.  You could post more comments here and I will try to answer them, or you can send me a message to my e-mail : Stefaan.Lesage@peopleware.be

Best regards,

Stefaan
0
 

Author Comment

by:pjelias
ID: 6243409
Stefaan,

thanks very much for all your help.

I may take your offer up about using templates a bit later.


pjelias.

0
 
LVL 3

Expert Comment

by:Stefaan
ID: 6243824
Hi,

Glad I could be of any assistance ;-)

Best regards and good luck,


Stefaan
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

744 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

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now