Board index » cppbuilder » TCollection, TCollectionItem ... FreeNotification

TCollection, TCollectionItem ... FreeNotification

Hi,
I have created a component property derived from a TCollection
(TTelMacroList) that stores another class derived from a TCollectionItem
(TTelMacro). The TTelMacro contains references to TWinControls and
everything seems to work fine in terms of storing and retaining the data. I
would like to have some form of notification should one of the controls be
deleted from the application, but am unsure how to achieve this.

I have tried using FreeNotification during the setting of the TTelMacro
property...
....
void __fastcall TTelMacro::SetControl1(TWinControl* ctrl)
{
    if (ctrl) FreeNotification((TComponent*)macrolist);
    control1 = ctrl;

Quote
}

then in the TTelMacroList class...

void __fastcall TTelMacroList::Notification(TComponent* AComponent,
TOperation Operation)
{

    if (Operation == opRemove)
    {
        for(int i = 0; i < Count; i++ )
        {
            TTelMacro* macro = dynamic_cast<TTelMacro*>(Items[i]);
            if (macro->control1 == AComponent) macro->control1 = NULL;
            ....

I suspect that this is causing me errors because the TTelMacroList Class is
derived from TTelCollection. Can anybody suggest a way that I may acheive
notification on a class derived from either a TCollection or a
TCollectionItem?

Thanks in advance, Cam

 

Re:TCollection, TCollectionItem ... FreeNotification


Notification only works for classes derived ultimately from TComponent.
Since the collection and collection items derive from TPersistent
instead they can not directly get notifications.

Therefore another method is needed to allow collections to deal with
notifications. The method that I use in my code is to create a class,
within my collection item ( or collection if that is what you want ),
derived from TComponent to handle the notification(s) and then use that
class to handle whatever notifications are needed by overriding the
virtual Notification method. You can add member functions to your
TComponent derived class so that it knows about whatever it needs to
react to notifications. Essentially your TComponent derived class acts
as a proxy for dealing with notifications.

Quote
Cam Ellis wrote:
> Hi,
> I have created a component property derived from a TCollection
> (TTelMacroList) that stores another class derived from a TCollectionItem
> (TTelMacro). The TTelMacro contains references to TWinControls and
> everything seems to work fine in terms of storing and retaining the data. I
> would like to have some form of notification should one of the controls be
> deleted from the application, but am unsure how to achieve this.

> I have tried using FreeNotification during the setting of the TTelMacro
> property...
> ...
> void __fastcall TTelMacro::SetControl1(TWinControl* ctrl)
> {
>     if (ctrl) FreeNotification((TComponent*)macrolist);
>     control1 = ctrl;
> }

> then in the TTelMacroList class...

> void __fastcall TTelMacroList::Notification(TComponent* AComponent,
> TOperation Operation)
> {

>     if (Operation == opRemove)
>     {
>         for(int i = 0; i < Count; i++ )
>         {
>             TTelMacro* macro = dynamic_cast<TTelMacro*>(Items[i]);
>             if (macro->control1 == AComponent) macro->control1 = NULL;
>             ....

> I suspect that this is causing me errors because the TTelMacroList Class is
> derived from TTelCollection. Can anybody suggest a way that I may acheive
> notification on a class derived from either a TCollection or a
> TCollectionItem?

> Thanks in advance, Cam

Re:TCollection, TCollectionItem ... FreeNotification


Quote
"Cam Ellis" <Cam.El...@Telenostra.no> wrote in message

news:3bf9149a_2@dnews...

Quote
> I have tried using FreeNotification during the setting of the TTelMacro
> property...
> ...
> void __fastcall TTelMacro::SetControl1(TWinControl* ctrl)
> {
>     if (ctrl) FreeNotification((TComponent*)macrolist);
>     control1 = ctrl;
> }

You are trying to call a FreeNotification() method that exists inside the
CollectionItem itself, but no such method really exists.  You need to call
the passed component's FreeNotification() method instead, ie:

    if (ctrl)
        ctrl->FreeNotification(TheMainComponent);

As Edward has already indicated, TCollection and TCollectionItem do not
support notifications (you should not have been able to register the
notification to begin with, but you did a hard cast from TCollection* to
TComponent* so the compiler was happy but it should have crashed at
runtime).  Thus you need to catch the notification in the main component
itself.

Quote
> Can anybody suggest a way that I may acheive notification on a class
derived
> from either a TCollection or a TCollectionItem?

Use the example above to help you register the main component to receive
notification from the passed component.  To allow access to the main
component from inside the individual collection items, you can add a new
property to your collection and override the constructor, ie:

class TTelMacroList : public TCollection
{
private:
    TComponent *FOwner;
public:
    __fastcall TTelMacroList(TComponent *AOwner, TMetaClass *ItemClass);
    __property TComponent* Owner = {read=FOwner};

Quote
};

__fastcall TTelMacroList::TTelMacroList(TComponent *AOwner, TMetaClass
*ItemClass)
    : TCollection(ItemClass)
{
    FOwner = AOwner;

Quote
}

void __fastcall TTelMacro::SetControl1(TWinControl* ctrl)
{
    if (ctrl)
        ctrl->FreeNotification( ((TTelMacroList*)Collection)->Owner );

    control1 = ctrl;

Quote
}

Then in the main component:

class TMainComponent : public TWhatever
{
private:
    TTelMacroList *FCollection;
public:
    __fastcall TMainComponent(TComponent *Owner);
    __fastcall ~TMainComponent();
    void __fastcall Notification(TComponent* AComponent, TOperation
Operation);

Quote
};

__fastcall TMainComponent::TMainComponent(TComponent *Owner)
    : TWhatever(Owner)
{
    FCollection = new TTelMacroList(this, __classid(TTelMacro));

Quote
}

__fastcall TMainComponent::~TMainComponent()
{
    delete FCollection;

Quote
}

void __fastcall TMainComponent::Notification(TComponent* AComponent,
TOperation Operation)
{
    if (Operation == opRemove)
    {
        for(int i = 0; i < FCollection->Count; i++ )
        {
            TTelMacro* macro =
dynamic_cast<TTelMacro*>(FCollection->Items[i]);
            if (macro->control1 == AComponent)
                macro->control1 = NULL;
        }
    }

Quote
}

You were on the right track with your original code, you were simply doing
it in the wrong places.

Gambit

Other Threads