Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Need to determin TObject ClassType & Name

Posted on 2006-06-28
12
Medium Priority
?
586 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
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

New feature and membership benefit!

New feature! Upgrade and increase expert visibility of your issues with Priority Questions.

Question has a verified solution.

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

In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
This is my first video review of Microsoft Bookings, I will be doing a part two with a bit more information, but wanted to get this out to you folks.
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…
Suggested Courses

704 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