Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Need to determin TObject ClassType & Name

Posted on 2006-06-28
12
Medium Priority
?
596 Views
Last Modified: 2010-04-05
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;
   
0
Comment
Question by:fibdev
  • 5
  • 4
  • 3
12 Comments
 
LVL 17

Expert Comment

by:TheRealLoki
ID: 17006195
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
0
 
LVL 3

Author Comment

by:fibdev
ID: 17006252
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;
0
 
LVL 3

Author Comment

by:fibdev
ID: 17006285
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;
0
Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

 
LVL 17

Accepted Solution

by:
TheRealLoki earned 300 total points
ID: 17006551
function GetObject(Sender: TObject): TObject;
var I: Integer;
    IT: TObject;
    sForm: TForm;
begin
    result := nil; // default
    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
        begin
            if i > 0 then // make sure this is not the first object in the list
              IT := sForm.Controls[(I-1)];
        end
      end;
   end;
   Result := IT;
//   IT.Free; <-- do not free this, or you will lose the object on the form! IT is just a pointer to it
end;

procedure TForm1.Button1Click(Sender: TObject);
var
    anobject: tobject;
begin
    anobject := getobject(button1);
    showmessage( (anobject as twincontrol).name);
end;

I'll write a tidier example in a min
0
 
LVL 17

Expert Comment

by:TheRealLoki
ID: 17006576
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;
0
 
LVL 3

Author Comment

by:fibdev
ID: 17008187
Thanks,

I'll look at it after work
0
 
LVL 6

Assisted Solution

by:House_of_Dexter
House_of_Dexter earned 300 total points
ID: 17012305
This one will recurse through all your wincontrols...and thier wincontrols...and thier wincontrols...until you find the sender...and then give you the previous object...

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] =  aObjectthen
         Result := aParent.Controls[a_iIndex -1];  
    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;

I use something similar to make all components visible for panels and such...passing the panel and then making its children visible or non visible...

procedure VisibleChildren(aParent: TWinControl; aVisible: boolean);
{this procedure will make Visible all the children and thier decendants}
var
  a_iIndex: integer;
begin
  for a_iIndex := 0 to aParent.ControlCount -1 do
  begin
  {we loop through all the children}
    TControl(aParent.Controls[a_iIndex]).Visible := aVisible;
    if 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.}
      VisibleChildren(TWinControl(aParent.Controls[a_iIndex]), aVisible);
  end;
end;
0
 
LVL 6

Expert Comment

by:House_of_Dexter
ID: 17012554
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;
0
 
LVL 3

Author Comment

by:fibdev
ID: 17014107
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.
0
 
LVL 17

Expert Comment

by:TheRealLoki
ID: 17014266
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.
0
 
LVL 6

Expert Comment

by:House_of_Dexter
ID: 17018790
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';
0
 
LVL 3

Author Comment

by:fibdev
ID: 17020411
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.
0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
Are you ready to place your question in front of subject-matter experts for more timely responses? With the release of Priority Question, Premium Members, Team Accounts and Qualified Experts can now identify the emergent level of their issue, signal…
Whether it be Exchange Server Crash Issues, Dirty Shutdown Errors or Failed to mount error, Stellar Phoenix Mailbox Exchange Recovery has always got your back. With the help of its easy to understand user interface and 3 simple steps recovery proced…
Suggested Courses

783 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question