Solved

Need to determin TObject ClassType & Name

Posted on 2006-06-28
12
543 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
 
LVL 17

Accepted Solution

by:
TheRealLoki earned 75 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
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 6

Assisted Solution

by:House_of_Dexter
House_of_Dexter earned 75 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

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
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…
Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.

705 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

Need Help in Real-Time?

Connect with top rated Experts

15 Experts available now in Live!

Get 1:1 Help Now