How can I determine whether a variable exists on a specified form?

I am trying to create a generic test routine to determine whether a form meets specified criteria.  At the moment I have to list each form that contains a particular variable in order to typecast the form to the correct type to allow the check...

          // Check ID match
          if Length(FormIDString) = 0 then // Any instance will do
            IDMatch := True
          else
            begin
              if f is TListEditDialog then // For ListEditDialog
                begin
                  IDMatch := (TListEditDialog(f).FormIDString = FormIDString);
                end;

              if f is TBillForm then // For BillFormDialog
                begin
                  IDMatch := (TBillForm(f).FormIDString = FormIDString);
                end;

              // other forms here, if the form is not listed the IDMatch default value of false is retained
            end;

I need to check whether the variable FormIDString exists in the form (f) that has been passed, and check its value if it does.  Can anyone suggest a better way that does not require the code to be modified any time a form is added to the project?

Chris Bray.
LVL 3
chrisbrayAsked:
Who is Participating?
 
OzzModConnect With a Mentor Commented:
Closed, 125 points refunded.
OzzMod
Community Support Moderator (Graveyard shift)
0
 
mikelittlewoodCommented:
Could you not use a simple text search technique instead.

Convert all your files to text (including forms) using the Convert.exe application that comes with Delphi,
Then just use the standard find in files tool and point it at *.DPR, *.pas, *.txt.
0
 
chrisbrayAuthor Commented:
Hi Mike,

No.  The whole point of the question is that the determination of existence has to be done at runtime - hence the code!!

This is a modular application and the forms that are available will vary depending on the specification the customer has chosen.  Being modular, other forms are likely to be added at a later date as additional options, plug-ins and functionality are added.  Therefore a design time check is pointless, not least because I already know whether the variable exists in the forms I have created and I can (as you can see from the code) hard code which ones do and do not.

I need to turn this into a generic routine that will work with any form...

If I were looking for a button I would use FindComponent, if that gives you any pointer?

Chris Bray.
0
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.

 
mikelittlewoodCommented:
Ok I see.
I must admit Im unsure if you could write anything so generic to handle this as you are specifically trying to find certain classes. If the application does not know the definitions of the class to start with, it cant check for any variables on the actual form itself. You cant assume that the application would suddenly be able to pass in a form its never heard of before and know what to be casting against.

I would say that the way you are doing it at the moment is possibly the only way that would do it.

I could be wrong, and if so Id like to hear an alternate answer myself so Ill watch the thread.
0
 
pritaeasSoftware EngineerCommented:
Well, if it needs to be done at run-time, you can still convert the form you want to test to text, using the ObjectBinaryToText() function. Then (in code) you can locate the FormIDString in the text, and even check it's value.

hth, pritaeas.
0
 
philipjcCommented:
polymorphism?

TMyForm = Class(tform)
        FormIDString : TString;


derive all forms from TMyForm

Set FormIDString in constructor

function IDMatch(f  : TMyForm; FormIDstring : TString) : Boolean
begin
      IDMatch := (f.FormIDString = FormIDString);
end;
0
 
chrisbrayAuthor Commented:
Hi guys,

Thanks for your input. However...

Priteas:  A VERY long way of finding out something incredibly simple which the system must already know!  Doing that literally hundreds of times during the operation of a program is *way* too much of a processing overhead particularly considering that as it is a variable it must be added to the stack at some point, and therefore Delphi must already know whether it exists or not...

Philipjc: I could just as easily add the variable to all forms, which would ensure that it always exists but is not the point and is a waste of time for forms that don't need it.  If I were to use your method I would also have to change every form in a very large application including multiple ancestor forms - not something that I want to embark upon to deal with a simple question of whether or not a particular variable exists.

I could also assign to the variable and trap any error that arises, but that would give rise to hundreds of entries in any error log that are unnecessary and unhelpful as well as being bad programming practice.

I am convinced that there is a simple way to do this with a minimum overhead, and am looking to find that method.

Chris Bray.
0
 
chrisbrayAuthor Commented:
I have found the answer for myself, and it is Properties that provide it:

(* In the form to be checked *)

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    fFormIDString: String;
  published
    property IDFieldString: String read fFormIDString write fFormIDString;
  public
    { Public declarations }
  end;

(* The check routine in a separate unit *)
// add var PropInfo: PPropInfo to routine
// add TypInfo to uses clause
begin
  // ................
  // other code here
  // ...............

          // Check ID match
          if Length(FormIDString) = 0 then // Any instance will do
            IDMatch := True
          else
            begin
              IDMatch := False;
              PropInfo := GetPropInfo(f.ClassInfo, 'FormIDString');
              if Assigned(PropInfo) then
                IDMatch := GetStrProp(f, PropInfo) = FormIDString;
            end;

          Existing := TagMatch and IDMatch;

  // ................
  // other code here
  // ...............

So, add a property to the ancestor form (or to the form itself if unique or
based on TForm) and away we go!  None of the existing code or post form
creation assignments are affected, so I have only had to add the property to
two forms to convert the entire application... Almost couldn't be better :-)

Having found the answer for myself I intend to request a points refund.

Chris Bray.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.