Link to home
Start Free TrialLog in
Avatar of chrisbray
chrisbrayFlag for United Kingdom of Great Britain and Northern Ireland

asked on

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.
Avatar of Mike Littlewood
Mike Littlewood
Flag of United Kingdom of Great Britain and Northern Ireland image

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.
Avatar of chrisbray

ASKER

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.
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.
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.
Avatar of philipjc
philipjc

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;
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.
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.
ASKER CERTIFIED SOLUTION
Avatar of OzzMod
OzzMod

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial