Icon View Thread

The following is the text of the current message along with any replies.
Messages 1 to 10 of 12 total
Thread Accessing objects with name as string
Mon, Feb 22 2016 6:31 PMPermanent Link

Trinione

Hi:
From Form2 I can see the object value from Form1 with:

ShowMessage(Form1.edtClientCode.Text);

However, setting the name to a variable does not work. For example:

clientCodeObjectName := 'Form1.edtClientCode';
ShowMessage(TEdit(clientCodeObjectName).Text);

How can a component be referenced by its component name stored in a string variable?
Mon, Feb 22 2016 9:43 PMPermanent Link

Raul

Team Elevate Team Elevate

On 2/22/2016 6:31 PM, Trinione wrote:
>  From Form2 I can see the object value from Form1 with:
> ShowMessage(Form1.edtClientCode.Text);
> However, setting the name to a variable does not work. For example:
> clientCodeObjectName := 'Form1.edtClientCode';
> ShowMessage(TEdit(clientCodeObjectName).Text);
> How can a component be referenced by its component name stored in a string variable?

Why do you need to find the components by name ? Reason i'm asking is
that there might be better ways to achieve what you want.

Normally you would reference the object itself and not its name.

Something like

var
 myEdit:TEdit;
begin
 myEdit := Form1.edtClientCode;
 ShowMessage(myEdit.Text))
 ...

at this point myEdit is a reference to the actual control instance so
you can do things like "ShowMessage(myEdit.Text))" etc.

If you really need to find the object by name then all container
controls (like Form) have a "Controls" property
(http://www.elevatesoft.com/manual?action=viewprop&id=ewb2&comp=TControl&prop=Controls)
which you can use to loop thru the controls and then check their name.
Se also ControlCount to know how many controls there are.

Controls themselves can be containers as well (like panels) so you need
to take this into account when doing this. however if just want to find
child controls of the form then simple loop thru the array and checking
control name should do it.

Raul
Mon, Feb 22 2016 10:26 PMPermanent Link

Trinione

<< Why do you need to find the components by name ?  >>

I have a selection list that I am displaying and need to return the value selected. to the calling form. Since the browser does not yield control to Form2, I need to set the value on Form1 from there. To do that I am passing the variable name 'Form1.edtClientCode' so from Form2 the value on Form1 can be set.

Now, if I need to call the list on Form2 from say Form5 I would do the same setting the value passed as 'Form5.edtTheClientCodeHere' or whatever the object name is on the calling form.
Mon, Feb 22 2016 10:40 PMPermanent Link

Trinione

To be clear, I need to set the value on the object on Form1 from Form2, as in:

(in Form2)
clientCodeObjectName := 'Form1.edtClientCode';
clientCodeObjectName.Text := 9999;

The value 'Form1.edtClientCode' was passed as a string parameter from Form1.
Tue, Feb 23 2016 2:15 AMPermanent Link

Uli Becker

> How can a component be referenced by its component name stored in a string variable?

This should work:

   s :=  TEdit(Form1.FindComponent('edtClientCode')).Text;
   showmessage(s);

Uli
Tue, Feb 23 2016 3:54 AMPermanent Link

Matthew Jones

Trinione wrote:

> To be clear, I need to set the value on the object on Form1 from
> Form2, as in:
>
> (in Form2)
> clientCodeObjectName := 'Form1.edtClientCode';
> clientCodeObjectName.Text := 9999;
>
> The value 'Form1.edtClientCode' was passed as a string parameter from
> Form1.

FWIW, this is the wrong way around. You will find things a lot easier
to go with the normal Delphi way of doing things. The key is that the
forms should have no knowledge of how they actually implement things.
So the form with the list will not know anything about the caller, but
instead will have a property to return the current selection. The
calling form will access that property. I've put together a simple
example below which shows this with a basic edit control on the
dataEdit form. You will find things work a lot better long term if you
do it this way. Even if you want to pass in an actual edit component,
then you could pass a reference to the real component to update and not
the name. But really that is an exception that needs very special
reasons.

--

Matthew Jones


// In the window which wants to show the dialog:

procedure TfrmCaller.ShowDialog;
begin
   if not assigned(frmAddressEdit) then
       frmAddressEdit := TfrmAddressEdit.Create(Application);
       
   frmAddressEdit.OnClose := DialogCallback;
   frmAddressEdit.MyText := 'Hello Mum';

   frmAddressEdit.ShowModal;
end;


procedure TfrmCaller.DialogCallback(Sender: TObject);
var
   szText : String;
begin
   szText := frmAddressEdit.MyText;
   // do something with it here
end;

// Skeleton of the dialog code

TfrmDataEdit = class(TDialog)
  editText: TEdit;
// other components snipped
private

   procedure SetMyText(szText : String);
   function GetMyText : String;
public
   property MyText : String read GetMyText write SetMyText;
end;


function TfrmDataEdit.GetMyText : String;
begin
   Result := editText.Text;
end;

procedure TfrmDataEdit.SetAddressJSON(szText : String);
begin
 editText.Text := szText;
end;
Tue, Feb 23 2016 10:19 AMPermanent Link

Trinione

Thank you both for your prompt suggestions.

Uli
This did work. Thank you.

<<     s :=  TEdit(Form1.FindComponent('edtClientCode')).Text; >>


Matthew:
Thanks for the advice. Correct, and I shall modify my skills accordingly.

In trying your code, it fails in procedure TfrmCaller.DialogCallback, at the following line:

szText := frmAddressEdit.MyText;

I suspect it is because it is a Modal form and the value is no longer available as the frmAddressEdit would have been Closed or Freed as per the way ShowModal works in EWB.

Is there a solution for this?
Tue, Feb 23 2016 11:32 AMPermanent Link

Matthew Jones

Trinione wrote:

> In trying your code, it fails in procedure TfrmCaller.DialogCallback,
> at the following line:
>
> szText := frmAddressEdit.MyText;
>
> I suspect it is because it is a Modal form and the value is no longer
> available as the frmAddressEdit would have been Closed or Freed as
> per the way ShowModal works in EWB.
>
> Is there a solution for this?

Fails in what way? The form should have the buttons set to be
ModalResult mrOK or similar. It should not be clearing the global
variable with the form object.

Probably best if you could post your real code, rather than my
contrived (edited down from a real dialog) code.

--

Matthew Jones
Tue, Feb 23 2016 12:23 PMPermanent Link

Trinione

<< Fails in what way? The form should have the buttons set to be
ModalResult mrOK or similar. It should not be clearing the global
variable with the form object. >>

That would work with ShowModal for sure.

I am calling the program with a Show so that's why it was not working.

Thanks.
Thu, Feb 25 2016 4:02 PMPermanent Link

Trinione

"Matthew Jones" wrote:

<< Probably best if you could post your real code, rather than my contrived (edited down from a real dialog) code. >>

Hi:
I receive 'Out of stack space ... Line 1' application error message when I try to run this code. What am I doing wrong?

procedure TfrmMain.Button1Click(Sender: TObject);
begin
 if Not Assigned(frmTestGetSet) then
   frmTestGetSet := TfrmTestGetSet.Create(nil);

 frmTestGetSet.Code := 999;
 ShowMessage(IntToStr(frmTestGetSet.Code));
end;


////////// formTestGetSet  //////////

type
  TfrmTestGetSet = class(TForm)
     procedure frmTestGetSetDblClick(Sender: TObject);
  private
     { Private declarations }                     
     iCode: integer;
     function GetCode: integer;
     procedure SetCode(Code: integer);
  public
     { Public declarations }
     property Code : integer read GetCode write SetCode;
  end;

var
  frmTestGetSet: TfrmTestGetSet;

implementation

function TfrmTestGetSet.GetCode : integer;
begin
 result := Code;
end;

procedure TfrmTestGetSet.SetCode(Code: integer);
begin
 iCode := Code;
end;
Page 1 of 2Next Page »
Jump to Page:  1 2
Image