[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 234
  • Last Modified:

Referencing Forms!

Hi

In VB I can do this
*************
Dim F as Form

Set F=FormEdit

F.show


Set  F=FormNew

F.Show

In Delphi this is not possible (or is it?). Because each form is a class of its own.

i.e.

Var F:TForm;

F:=FormEdit;

F.show;

The above works!

However, if I add a textbox control to FormEdit it doesn't work because the base class of TForm doesn't have a text box but TFormEdit does!

Like so

Var F:TForm;

F:=FormEdit;

F.editbox1.text:='xvxcv';
F.show;

This naturally fails!

What I am trying to do is this.

I have several forms for different purposes.  But each form uses the same Lookup Form for looking up the same data.  It always inserts the same data into the same named controls but on different forms.

The scripts are quite long and complex, is there a way of running the same script against different forms without repeating the same script 5 or 6 times like this.

If (FEdit1<>nil) and (FEdit1.visible=true) then

Begin

//long script
//********
FEdit1.TBDescripion:='sdfsdfsdfsd';

etc.


End;


If (FEdit2<>nil) and (FEdit12.visible=true) then

Begin

//long script
//********
FEdit2.TBDescripion:='sdfsdfsdfsd';

etc.


End;


The script is always the same but refers to different forms


Voodooman







0
Voodooman
Asked:
Voodooman
  • 6
  • 4
  • 2
  • +1
1 Solution
 
EddieShipmanCommented:
Go with the ancestor....

Change to this:

procedure DoForm(Form: TCustomForm);
begin
  if Form is TFormEdit then
    TFormEdit(Form).editbox1.text:='xvxcv';
  if Form is TFormNew then
    TFormNew(Form).editbox1.text:='xvxcv';
  Form.show;
end;

Called like this:
DoForm(FormEdit);
DoForm(FormNew);


Then it should work for you...

0
 
VoodoomanAuthor Commented:

Hi Eddie

I see where you are coming from but this is not what I am asking.

What I am looking to do is something like this.

procedure TForm1.Button1Click(Sender: TObject);

var F:TForm;
begin

//FEditClient loaded
//*************
If FEditClient<>Nil then F:=FEditClient;

//FNewClient loaded
//*************
If FNewClient<>Nil then F:=FNewClient;

//Fill a text box with the same name - never mind which form its on!
//************************************************
F.Edit1.Text:='xxxxx';



end;

The idea is not to repeat the same script (200 lines) for each form - its easy to do this in VB(clunker....).  I am existingly usind the script you suggest.

Thanks for your input

Voodooman

0
 
BlackTigerXCommented:
using the ancestor in a slightly different way

procedure ShowTextInXForm(F:TForm; const Text:string);
var
  aEdit:TEdit;
begin
  f.Show;
  aEdit:=TEdit(F.FindComponent('Edit1'));
  aEdit.Text:='hola'
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  aEdit:TEdit;
begin
  ShowTextInXForm(Form2, 'hola');
  ShowTextInXForm(Form3, 'hola');
end;

0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
EddieShipmanCommented:
I gotcha, BlackTigerX has the answer, then.

I didn't totally understand what you wanted to do.
0
 
VoodoomanAuthor Commented:

Hi  

Thanks BTX I will try it later - kooks very good, gotta go out to a client - they get in the way of the programming!

Thanks

Voodooman
0
 
VoodoomanAuthor Commented:
Hi Guys

I am in big trouble with this.

BlackTigerX solution works in a quick test, but falls over everywhere with 'Invalid Floating Point Error' when I try to set a combo box ItemIndex or a numeric value to a custom edit control.


This fails with the error as above

TBUnitPrice.Value:=UnitPrice;

With a normal assignment it works fine


However this succeeds!

TBDescription.Text:=Description;

It seems that numbers fail in some way - the numbers are correctly cast!



Voodooman



0
 
EddieShipmanCommented:
I don't think it is a failing of BTX's code, post the rest of your so we can see what you're doing.
0
 
VoodoomanAuthor Commented:

Hi Eddie

I can no problem post values to TextBoxes, but can't seem to assign numerical values.

Here is my code, I  have changed the code in my program as I have a simple work around, so the code here is not run and there may be some small typos (need to get the job done). I can work around it by assigning values to an object I have created and filling the form after my modal form closes like this.

F_Edit.showmodal;

TBDescription.text:=dataobj.LookupDescription;
CBUnit.ItemIndex:=dataobj.LookuoItemIndex;
etc

This saves a lot of code and is easier to maintain than before.


This code is a reconstruction of the code I was running.

procedure TF_Lookup.B_InsertClick(Sender: TObject);

var Description:string;
    UnitDescription:string;
    UnitPrice:double;
    GetItem:string;
    TBDescription:TEdit;
    TBQty:TEdit;
    CBUnit:TComboBox;
    TBUnitPrice:Tvg2CalculatorEdit;
    F:TForm;
    getIndex:Integer;

  begin



    Try

    if DataObj.QLookup.RecordCount=0 then
       Begin
       Imessage('No Items found to Insert!');
       TB_Find.SetFocus;
       Exit;
       end;

    //Get the data
    //************

    Description:=dataObj.QLookup.FieldValues['Description'];
    UnitDescription:=dataObj.QLookup.FieldValues['Unit'];
    UnitPrice:=dataObj.QLookup.FieldValues['UnitPrice'];



    //Need to grab the controls for filling on the underlying active form into vars
    //*****************************************************************************

    //Edit Summary Item
    //******************
    if F_EditSummaryItem<>nil then
          if F_EditSummaryItem.Visible=true then
          Begin
          F:=F_EditSummaryItem;
          CBUnit:=TComboBox(F.FindComponent('CBUnit'));
        TBDescription:=TEdit(F.FindComponent('TBDescription'));
        TBUnitPrice:=Tvg2CalculatorEdit(F.FindComponent('TBUnitPrice'));      
          end;

    //Edit Item
    //******************
    if F_EditItem<>nil then
          if F_EditItem.Visible=true then
          Begin
          F:=F_EditItem;
          CBUnit:=TComboBox(F.FindComponent('CBUnit'));
          TBDescription:=TEdit(F.FindComponent('TBDescription'));
          TBUnitPrice:=Tvg2CalculatorEdit(F.FindComponent('TBUnitPrice'));      
          end;

    //New Item
    //******************
    if F_NewItem<>nil then
          if F_NewItem.Visible=true then
          Begin
          F:=F_NewItem;
          CBUnit:=TComboBox(F.FindComponent('CBUnit'));
          TBDescription:=TEdit(F.FindComponent('TBDescription'));
          TBUnitPrice:=Tvg2CalculatorEdit(F.FindComponent('TBUnitPrice'));      
          end;


    //Need to get the index of the unit - to make sure it still exists
    //****************************************************************
    //and to set the value of the Combo
    //*********************************

    getIndex:=CBUnit.Items.IndexOf(UnitDescription);

    //Cant assign the ComboBox Item Index - it doesn't work
    //*****************************************************
    //Instead set DataProject.LookupIndex and use it to fill the list box when the modal form closes
    //**********************************************************************************************
    if getIndex<>-1 then  //if it exists
      Begin  
      CBUnit.ItemIndex:=getIndex;
      TBUnitPrice:=UnitPrice;
      end
      Else
      Begin
      Imessage('Unit ' + quotedStr(UnitDescription) + ' is no longer in your Unit List - only the Description will be added!');
      CBUnit.ItemIndex:=-1;
      TBUnitPrice:=0;
      end;

    TBDescription:=Description;
   


    Self.Close;

    except On E:Exception do
           EMessage('Error filling lookup fields - ' + E.Message);

    end;


    end;


I can assign to the TBDescription but cannot assign the  ComboBox or the Numeric value to the TVG2Calculator.  I can do this using the actual form name - no problem.

Please note, I am not one of those people who ask for help and try and get out of giving the points!  I am a professional programmer and always looking to learn! Happy to give the points!

Voodooman
0
 
gandalf_the_whiteCommented:
if you use a BaseForm that is the ancestor of all your forms could this solve your problem?

type Baseform = class (TForm)
       { here are all controls that your form have in }
       Edit1:TEdit;
       end;

type  FEditClient = class(TBaseForm)
        ...
       end;


type  FNewClient = class(TBaseForm)
        ...
       end;


you now use the following code

var F:TBaseForm;
begin

//FEditClient loaded
//*************
If FEditClient<>Nil then F:=FEditClient;

//FNewClient loaded
//*************
If FNewClient<>Nil then F:=FNewClient;

//Fill a text box with the same name - never mind which form its on!
//************************************************
F.Edit1.Text:='xxxxx';

all things that are shared by all the forms  must be declared and implemented in
the base class (and can be used with the generic F variable).

i am not sure if i understood your problem and the thing you want to do

regards
0
 
VoodoomanAuthor Commented:

Hi gandalf_the_white

I think see what you mean.  Would I not have to position all the controls etc in the form create event?  The controls would have no positions and no code attached to them or would they?

What I am doing is filling forms from a lookup form.  In my case I am adding and editing items in a quotation system.  

The user can search previous quotes for similat items and insert them.  This is all fine.  However, because of how the data is structured and the views that are available I must have three different forms for Adding, Editing and AddingSummary Items.

The lookup form is identical in each case but there are 3 add/edit forms.  There is quite a lot of logic around whether the Looked up item can actually be used, which meands that for each form there is maybe 200 lines of code to fill each form.  I was looking to pass the form to a procedure something like this.


Procedure FillForm(F:TForm);

Begin



F.TBDescription:=Self.TBDescription;


End;
 
BlackTigerX solution works with Textbox but not with ComboBox or Custom Edit Control.


Voodooman
0
 
gandalf_the_whiteCommented:
hmmm
i am not sure if i understood it

what i mean is that you would not automatically create the base form in the project source code
(like:   Application.CreateForm(TBaseForm, BaseForm);)
just put it out of the autocreation part of the projectoptions)

if  parts of your three forms are the same (that means all three forms
have for instance CBUnit,  TBDescription,   TBUnitPrice   ) then
you put these three controls on you base form.

this base form is an object you never really use (or better of which you never create an instance).
the three forms you use are childs of this base form and you can create them like any other
object in dephi.

only problem is, that this three forms are not more visually availlable. that means if you have many differences
between them you have to code them and not just drag and drop them.
but if they share many things you should put them all into the base form.
btw you can even put things on the base form that are not shared by all three and
then make them visible in the oncreate method of the corresponding form.

the references to the objects should work in this way as all three objects are base forms
and base form has all properties public so you can have a variable that can
contain each one of the forms and change them.
0
 
EddieShipmanCommented:
If he uses a TFrame and drops the frame on each of his forms, he can name all the controls the same, the frames the same and
he can also modify each frame on each form as he sees fit.

Then all he would have to do is to prefix the framename with his formname like:

Then the code in my first post would become:

procedure DoForm(Form: TCustomForm);
begin
  Form.Frame1.Editbox1.Text:='xvxcv';
  Form.show;
end;

Called like this:
DoForm(FormEdit);
DoForm(FormNew);
0
 
VoodoomanAuthor Commented:

Thanks all, BlackTigerX's solution was what I was looking for in principle, but gave me errors with all but very  basic controls.

It's the ideas that count for the future.  I ended up with a neat and simple solution by simply creating an object and posting the entries to it.  I then simply filled the form after the show modal ended.

This meant that the data manipulation was always the same (as I was filling the object rather that the underlying forms).  This reduced the code and it's maintenance a lot.

Thanks again

BTX had the idea of what I was trying to do and I give him the points.

Voodooman

0
 
BlackTigerXCommented:
>>I ended up with a neat and simple solution...
that's how it should be, good for you, I'm glad to hear that

thanks
0

Featured Post

Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

  • 6
  • 4
  • 2
  • +1
Tackle projects and never again get stuck behind a technical roadblock.
Join Now