Link to home
Start Free TrialLog in
Avatar of fibdev
fibdev

asked on

Need to determin TObject ClassType & Name

Hello,

I need to determine the ClassType and Name of the TObject created before the sender...

procedure MyProcedure(Sender: TObject);
var TheAnswer: TObject;
begin
    If Sender.ClassType = TForm then
            DoMyFormProcedure(TForm(Sender))
    else
    // begin MyProcedure where I need TheAnswer
    // Insert Code to Determine the TObject created before Sender
    // Then I can use it...
end;
   
Avatar of TheRealLoki
TheRealLoki
Flag of New Zealand image

can you explain this more?
What kind of objects are these? are they user created TSomeUnknownObject, or are they child objects of the form?
are they "controls" ?
If the object is in a list, you could iterate through the list comparing each, and return the value before the index of the object if you find it. If it's a form's control, you can use the form1.controls[i] list
Avatar of fibdev
fibdev

ASKER

Loki,

Yes, I did that... Let me update you!

Here is where I am now...

...
var ClassRef: TClass;
begin
   // I wrote a function GetObject(Sender)
   // It returns the object i need, but...
   ClassRef := GetObject(Sender).ClassType;
   // this works... but
    If ClassRef.ClassName(Sender).Align = alLeft then
      Align := 'left';  // I get *too many actual params*
...

function GetObject(Sender: TObject): TObject;
var I: Integer;
    IT: TObject;
begin
   oList := TObjectList.Create;
   If oList.Count > 0 then
   begin
      for I := 0 to oList.Count - 1 do
      begin
        if oList.Items[I] = Sender then
          IT := oList.Items[(I-1)];
      end;
   end;
   Result := IT;
   IT.Free;
end;
Avatar of fibdev

ASKER

I noticed a problem and updated GetObject...

function GetObject(Sender: TObject): TObject;
var I: Integer;
    IT: TObject;
    sForm: TForm;
begin
    sForm := Application.MainForm;
    sForm.controls
   If sForm.ControlCount > 0 then
   begin
      for I := 0 to sForm.ControlCount - 1 do
      begin
        if sForm.Controls[I] = Sender then
          IT := sForm.Controls[(I-1)];
      end;
   end;
   Result := IT;
   IT.Free;
end;
ASKER CERTIFIED SOLUTION
Avatar of TheRealLoki
TheRealLoki
Flag of New Zealand image

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
This is a little better.
It stops once it finds teh object, so it is faster, and cleaner

function GetObject(Sender: TObject): TObject;
    var
        i, ourobjectindex: Integer;
    begin
        result := nil; // default
        i := 0;
        ourobjectindex := -1;
        while (ourobjectindex = -1) and (i < Application.MainForm.ControlCount) do
        begin
            if Application.MainForm.Controls[i] = Sender then
              ourobjectindex := i
            else inc(i);
        end;
        if ourobjectindex > 0 then // make sure this is not the first object in the list
          result := Application.MainForm.Controls[ourobjectindex-1];
    end;

procedure TForm1.Button1Click(Sender: TObject);
    var
        anobject: tobject;
    begin
        anobject := getobject(button1);
        if anobject <> nil then
          showmessage( (anobject as twincontrol).name)
        else
          showmessage('object is the first in the list');
    end;
Avatar of fibdev

ASKER

Thanks,

I'll look at it after work
SOLUTION
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
function GetPrevObject(aParent: TWinControl; aObject: TObject): TObject;
var
  a_iIndex: integer;
begin
  Result := nil;
  for a_iIndex := 0 to aParent.ControlCount -1 do
  begin
  {we loop through all the children}
    if a_iIndex > 0 then
      if aParent.Controls[a_iIndex] =  aObject then
      begin
         Result := aParent.Controls[a_iIndex -1];
         exit;//<--added to jump out faster...
      end;
    if (Result = nil) and (aParent.Controls[a_iIndex] is TWinControl) then
{if its a WinControl...meaning it can be a Parent to other controls...we loop
 through them, and so and so on.}
      Result := GetPrevObject(TWinControl(aParent.Controls[a_iIndex]), aObject);
  end;
end;

{Test code...remember to check if assigned before using the object...because can be nil...as in example }

procedure TForm1.Button2Click(Sender: TObject);
var
  a_PrevObject: TObject;
begin
  a_PrevObject := GetPrevObject(Form1, Sender);
  if Assigned(a_PrevObject) then
    if a_PrevObject is TButton then
      TButton(a_PrevObject).Caption := 'Previous';
end;
Avatar of fibdev

ASKER

Ok,

I've looked at both examples...

What I'm trying to do is use a property from the WinControl created before the one I reference as Sender. The hitch is... I want to do this without knowing the ClassType of said WinControl.
So givin, this won't do :(

    if a_PrevObject is TButton then
      TButton(a_PrevObject).Caption := 'Previous';

I'm trying to avoid a lengthy case statement that may or may not miss a WinControl.
if you want to use a property of a control, that's fine, eg. (anobject as tcontrol).parent  or (anobject as twincontrol).bevelinner...

if you want to be specific and set a "caption" of a control, then you _will_ need to check if it has that property
(by "is tlabel" for example)
I would not recommend doing :-
try
    (anonbect as tlabel).caption := 'test'; // anobject may not be a TLabel, so this will generate an error
except
end;

and ignoring the error when the typecast fails.

You might need to explain a bit more to us about what you are trying to do. Perhaps there is a more obvious solution we could provide.
If your trying to change a Non Polymorphic property...there is no way around having to write some type of Type conversion...

but if your trying to change a Polymorphic property like Caption...

Label1.Caption := 'My Caption'

Caption is Polymorphic...it is in TControl...but protected...so you can do something like this

declare this in the Interface...

type
  THackControl = class(TControl)
  public
    property Caption;
end;



Your code...

  if Sender is TControl then
    THackControl(Sender).Caption := 'My Caption';
Avatar of fibdev

ASKER

I've givin the whole of my code to someone I trust and know to have vast knowlage of Delphi.  He tells me that what I'm trying to do is not practical because the controls are listed in an arbitrary order.

Thank you guys for trying, but I think I'm going to take a different approach.