Board index » cppbuilder » Accessing properties of an object passed in as TObject *Sender in an event function

Accessing properties of an object passed in as TObject *Sender in an event function

I need to be able to access properties of an object that triggered an event
function. I have a function that is used by multiple objects in either the
OnClick or OnChange event. I need to know the exact object as I require a
value from a property within that object. These objects are created at
runtime.

Can I use the TObject *Sender parameter to do this? I tried doing something
like this:

bool __fastcall TAddUsernameListForm::AddUserIfLastOnList(TObject *Sender)
{
 TNewUser *lastuser, *thisuser;
 char str[255];

 thisuser = (TNewUser *)UserList->Items[dynamic_cast<TFEISEdit
*>(Sender)->Row];
.
.
.

Quote
}

[TFEISEdit is a TEdit with one extra property added: int Row,
 TNewUser is a struct of pointers to various VCL objects (modified with the
additional property Row),
 UserList is a TList containing a sequence of TNewUser structs representing
a row on a form]

It doesn't work. Also I have done a dynamic_cast to the TFEISEdit class but
not all of the objects that use the function are of the same class. So I
also need a way of typecasting it to the correct type.

Am I using the Sender parameter incorrectly? Does it represent the actual
object that triggered the event or do I need to find another way to do this?

I'm sure this description is too vague so please tell me if any further
information would be helpful.

Thanks,
--

Matt Ross
Please remove all underscore characters from my e-mail address.

 

Re:Accessing properties of an object passed in as TObject *Sender in an event function


Quote
"Matt Ross" <m._g._ross@_herts._ac._uk> wrote in message

news:3cda715e$1_2@dnews...

Quote
> Can I use the TObject *Sender parameter to do this?

Sender is a pointer to the actual object that triggered the event, yes.

Quote
> It doesn't work.

Is the event handler actually assigned to a TFEISEdit instance?
dynamic_cast will fail if Sender is not actually a TFEISEdit object.

Also, you should always check the return value of dynamic_cast before using
the object, because dynamic_cast returns NULL if it fails:

    TFEISEdit *edit = dynamic_cast<TFEISEdit*>(Sender);
    if(edit)
        thisuser = (TNewUser *)UserList->Items[edit->Row];

Quote
> Also I have done a dynamic_cast to the TFEISEdit class but not all
> of the objects that use the function are of the same class. So I also need
> a way of typecasting it to the correct type.

Then you either need to perform multiple casts until it finds one that
works, or you need to derive your objects from a common base class that you
can then cast to instead (if they don't already).

What other object types also use this function?

Gambit

Re:Accessing properties of an object passed in as TObject *Sender in an event function


"Remy Lebeau [TeamB]" <gambi...@yahoo.com> wrote in message
news:3cdab063$1_1@dnews...

Quote

> "Matt Ross" <m._g._ross@_herts._ac._uk> wrote in message
> news:3cda715e$1_2@dnews...

> > Can I use the TObject *Sender parameter to do this?

> Sender is a pointer to the actual object that triggered the event, yes.

Oh good so I'm on the right track.

Quote
> > It doesn't work.

> Is the event handler actually assigned to a TFEISEdit instance?
> dynamic_cast will fail if Sender is not actually a TFEISEdit object.

> Also, you should always check the return value of dynamic_cast before
using
> the object, because dynamic_cast returns NULL if it fails:

>     TFEISEdit *edit = dynamic_cast<TFEISEdit*>(Sender);
>     if(edit)
>         thisuser = (TNewUser *)UserList->Items[edit->Row];

Yes the event handler is assigned inside various object types (listed
below). Excellent, I was wondering how I could get it to tell what type it
was being called from.

Quote
> > Also I have done a dynamic_cast to the TFEISEdit class but not all
> > of the objects that use the function are of the same class. So I also
need
> > a way of typecasting it to the correct type.

> Then you either need to perform multiple casts until it finds one that
> works, or you need to derive your objects from a common base class that
you
> can then cast to instead (if they don't already).

> What other object types also use this function?

The full list is:
    TFEISEdit (descended from TEdit)
    TFEISCheckBox (descended from TCheckBox)
    TFEISComboBox (descended from TComboBox)
    TFEISCSpinEdit (descended from TCSpinEdit in the Samples tab)
    TFEISSpeedButton (descended from TSpeedButton)

Each of these classes adds only 1 new property: int Row. I use this to
determine what row on the form they are on as each row represents
information on one new user. Each row includes: Username, Surname,
Forenames, Windows, Unix, Type (i.e. Staff or Student), Quota, Delete this
row button. An example of one of these class declarations follows:

class TFEISEdit : public TEdit
{
__published: // IDE-managed Components
private: // User declarations
public:  // User declarations
 int Row;

 virtual __fastcall TFEISEdit(TComponent* Owner);

Quote
};

What I've noticed is that if I use dynamic_cast like this:
dynamic_cast<TFEISEdit*>(Sender) (currently only to the TFEISEdit type but I
will change it) I get this kind of error:
    'Unresolved external TFEISEdit:: referenced from........'

These classes are defined in the header file of the form that uses them.
What am I missing?

Thanks for your help. I was beginning to think I would have to re-work my
code to do this, now it looks like I'm close to a solution.

--

Matt Ross
Please remove all underscore characters from my e-mail address.

Re:Accessing properties of an object passed in as TObject *Sender in an event function


I have modified the code in my event triggered function to handle different
object types in the Sender object. It now looks like this:

-----start-----
 TNewUser *lastuser, *thisuser;
 TFEISEdit *editbox;
 TFEISCheckBox *checkbox;
 TFEISComboBox *combobox;
 TFEISCSpinEdit *cspinedit;
 TFEISSpeedButton *speedbutton;
 char str[255];

 if (UserList->Count > 0)
  lastuser = (TNewUser *)UserList->Items[UserList->Count - 1];
 else
  return false;

 if ((editbox = dynamic_cast<TFEISEdit *>(Sender)) != NULL) {
  // Sender is a TFEISEdit object
  thisuser = (TNewUser *)UserList->Items[editbox->Row];
 } else if ((checkbox = dynamic_cast<TFEISCheckBox *>(Sender)) != NULL) {
  // Sender is a TFEISCheckBox
  thisuser = (TNewUser *)UserList->Items[checkbox->Row];
 } else if ((combobox = dynamic_cast<TFEISComboBox *>(Sender)) != NULL) {
  // Sender is a TFEISComboBox
  thisuser = (TNewUser *)UserList->Items[combobox->Row];
 } else if ((cspinedit = dynamic_cast<TFEISCSpinEdit *>(Sender)) != NULL) {
  // Sender is a TFEISCSpinEdit
  thisuser = (TNewUser *)UserList->Items[cspinedit->Row];
 } else if ((speedbutton = dynamic_cast<TFEISSpeedButton *>(Sender)) !=
NULL) {
  // Sender is a TFEISSpeedButton
  thisuser = (TNewUser *)UserList->Items[speedbutton->Row];
 }
------end------

The object types I have created are defined in the header file of the form
they are used on, above the form's own class definition. When I compile the
project the linker cannot find these descended types (Unresolved external
TFEISEdit:: referenced from........). What do I have to do to help the
linker see these types? Obviously the header file is included in the .cpp
file of the unit so I cannot understand why it cannot find these types. I
also tried moving the new types to a separate .h and including it in the
form's header file, but it gave the same error.

Thanks,
--

Matt Ross
Please remove all underscore characters from my e-mail address.

Re:Accessing properties of an object passed in as TObject *Sender in an event function


Quote
> The object types I have created are defined in the header file of
> the form they are used on, above the form's own class
> definition. When I compile the project the linker cannot find these
> descended types (Unresolved external TFEISEdit:: referenced
> from........). What do I have to do to help the linker see these
> types? Obviously the header file is included in the .cpp file of the
> unit so I cannot understand why it cannot find these types. I also
> tried moving the new types to a separate .h and including it in the
> form's header file, but it gave the same error.

The header may be defining the type, but are the member functions
defined inside the class definition too?  If not, be sure that you've
actually implemented the member functions that are not linking, and
that they're in a .cpp file, and that .cpp file is included in your
project (so that it gets compiled!)

Also, check your spelling, make sure that the defintions of the member
functions actually are declared to be member functions and not
free-standing functions, etc.

If none of the above helps, please post the header file (trimmed of
code unrelated to this problem), and post the code that implements the
members that don't link.)

--
Chris(TeamB);

Re:Accessing properties of an object passed in as TObject *Sender in an event function


"Chris Uzdavinis [TeamB]" <ch...@atdesk.com> wrote in message
news:3cdf9607$1_2@dnews...

Quote

> > The object types I have created are defined in the header file of
> > the form they are used on, above the form's own class
> > definition. When I compile the project the linker cannot find these
> > descended types (Unresolved external TFEISEdit:: referenced
> > from........). What do I have to do to help the linker see these
> > types? Obviously the header file is included in the .cpp file of the
> > unit so I cannot understand why it cannot find these types. I also
> > tried moving the new types to a separate .h and including it in the
> > form's header file, but it gave the same error.

> The header may be defining the type, but are the member functions
> defined inside the class definition too?  If not, be sure that you've
> actually implemented the member functions that are not linking, and
> that they're in a .cpp file, and that .cpp file is included in your
> project (so that it gets compiled!)

Yes you are right. I had not configured the classes correctly. It was a
missing constructor definition, that was causing the linking problem. I have
also had to provide the default constructor for the base class of my derived
object classes. An example is below:

class TFEISEdit : public TEdit
{
public:
 int Row;

 __fastcall TFEISEdit(TComponent* Owner) : TEdit(Owner) {
  Row = -1;
 };

Quote
};

Now that I have created the constructor inline it compiles happily. I'm just
starting C++ so this is all new information to me.

Thanks for your help.

--

Matt Ross
Please remove all underscore characters from my e-mail address.

Other Threads