Ok Myles, you're absolutely right, I apologise.  This certainly seems to
be screwy.  Yes, TComponent.DestroyComponents is the culprit - no
notification is sent to the list of components before deletion, despite
what the help states.

>However this appears to be NOT the case. No OpRemove notification sent
is if the component being removed is descended
>from TComponent eg TQuery etc - It does work if you remove a TControl
or TWinControl.

Actually its even worse - this is only true as long as the TControl or
TWinControl has the form as a parent (change TComponent to TWinControl
in the sample code below and it still won't work).  TWinControl.Destroy
cleans up the list of controls properly, but the list of components is
another matter.

>Remove(Instance); // IF THIS WAS RemoveComponent then all would be
okay, or if TComponent.Remove did not set the owner to NIL.

Yes, IMO it's a serious bug/stuff up.  Replacing Remove with
RemoveComponent seems to be the best solution (as you suggested).

Cheers,

Carl Reynolds                      Ph: +64-9-4154790
CJN Technologies Ltd.             Fax: +64-9-4154791
[EMAIL PROTECTED]                DDI: +64-9-4154795
PO Box 302-278, North Harbour, Auckland, New Zealand
12 Piermark Drive, North Harbour Estate, Auckland, NZ
Visit our website at http://www.cjntech.co.nz/

> -----Original Message-----
> From: [EMAIL PROTECTED] [SMTP:[EMAIL PROTECTED]]
> Sent: Tuesday, July 06, 1999 5:56 PM
> To:   '[EMAIL PROTECTED]'
> Subject:      RE: [DUG]:  Notification Bug on Remove???
> 
> That is what I expect for that case.
> 
> Try this - Close the form after creating the components. ie press
> button 1, then close the form.
> You are correct, it you free them then you will get the notifications.
> The problem only arises when the Form (the components owners) does the
> destroy/free instead.
> Myles.
> 
> 
> -----Original Message-----
> From: Carl Reynolds [SMTP:[EMAIL PROTECTED]]
> Sent: Tuesday, July 06, 1999 4:20 PM
> To:   Multiple recipients of list delphi
> Subject:      RE: [DUG]:  Notification Bug on Remove???
> 
> Hmmm.  Well, I knocked together a sample form to test things:
> 
> unit Unit1;
> 
> interface
> 
> uses
>   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
> Dialogs,
>   StdCtrls;
> 
> type
>   TMyComponent = class(TComponent)
>   protected
>       procedure Notification(AComponent: TComponent; Operation:
> TOperation); override;
>   end;
> 
>   TMyComponent2 = class(TComponent)
>   protected
>       constructor CreateMe(POwner: TComponent; PNotifyComponent:
> TComponent);
>   end;
> 
>   TForm1 = class(TForm)
>       Button1: TButton;
>       Button2: TButton;
>       Button3: TButton;
>       procedure Button1Click(Sender: TObject);
>       procedure Button2Click(Sender: TObject);
>       procedure Button3Click(Sender: TObject);
>   private
>       MyComponent: TMyComponent;
>       MyComponent2: TMyComponent2;
>   end;
> 
> var
>   Form1: TForm1;
> 
> implementation
> 
> {$R *.DFM}
> 
> 
> procedure TMyComponent.Notification(AComponent: TComponent; Operation:
> TOperation);
> begin
>       inherited;
>       if (AComponent is TMyComponent2) and (Operation = opRemove) then
> begin
>               ShowMessage('Can''t say I wasn''t told...');
>       end;
> end;
> 
> constructor TMyComponent2.CreateMe(POwner: TComponent;
> PNotifyComponent: TComponent);
> begin
>       inherited Create(POwner);
>       FreeNotification(PNotifyComponent);
> end;
> 
> procedure TForm1.Button1Click(Sender: TObject);
> begin
>       MyComponent := TMyComponent.Create(Self);
>       MyComponent2 := TMyComponent2.CreateMe(Self, MyComponent);
> end;
> 
> procedure TForm1.Button2Click(Sender: TObject);
> begin
>       MyComponent2.Free;
> end;
> 
> procedure TForm1.Button3Click(Sender: TObject);
> begin
>       MyComponent.Free;
> end;
> 
> end.
> 
> and if I click the buttons in order, my component receives OpRemove
> notification when I click button 2, as expected.  And they're
> non-visual components, so no problem there.  And both component have
> the same owner - I tried it with nil as an owner and it still worked.
> That's using FreeNotification.
> 
> >Can't use FreeNotification as it checks who the owner of the two
> components are and if they are the same it does not add it to the
> >FreeNotifies list. Tried that one already.
> 
> Well, it seemed to.  Did I miss something?
> 
> Cheers,
> 
> Carl Reynolds                      Ph: +64-9-4154790
> CJN Technologies Ltd.             Fax: +64-9-4154791
> [EMAIL PROTECTED]                DDI: +64-9-4154795
> PO Box 302-278, North Harbour, Auckland, New Zealand
> 12 Piermark Drive, North Harbour Estate, Auckland, NZ
> Visit our website at http://www.cjntech.co.nz/
> 
> -----Original Message-----
> From: [EMAIL PROTECTED] [SMTP:[EMAIL PROTECTED]]
> Sent: Tuesday, July 06, 1999 3:14 PM
> To:   '[EMAIL PROTECTED]'
> Subject:      RE: [DUG]:  Notification Bug on Remove???
> 
> That's the whole POINT it DOES NOT WORK. Have now spent several hours
> tracing through the source code using the Debugger to check what was
> occurring - I did not believe this was the problem initially. 
> 
> I only found it during testing of Creation Order of Components and
> having Contructors throw exceptions during Form creation to test the
> components destructors cleanup code (which failed of course) as no
> Notification( , OpRemove) was received as the Non-Visual components
> were destroyed.
> 
> I was VERY surprised to find the OpRemove notifications not working
> for Non-Visual components eg TDatabase, TQuery etc - Any TControl or
> TWinControl does not have this problem, as they get destroyed in
> TWinControl.Destory, and hence do not have this problem,
> 
> Can't use FreeNotification as it checks who the owner of the two
> components are and if they are the same it does not add it to the
> FreeNotifies list. Tried that one already.
> 
> Seems like the only solution is to change TComponent.DestroyComponents
> to call RemoveComponent instead of Remove.
> Myles.
> 
> 
>       -----Original Message-----
>       From:   Carl Reynolds [SMTP:[EMAIL PROTECTED]]
>       Sent:   Tuesday, July 06, 1999 2:36 PM
>       To:     Multiple recipients of list delphi
>       Subject:        RE: [DUG]:  Notification Bug on Remove???
> 
>       If you want a component (TMyComponent) to be notified about
> another component being freed, eg. when one of its sub-components
> (TMySubComponent) is removed, call
> TMySubComponent.FreeNotification(TMyComponent) at some point, usually
> during TMySubComponent's construction.  Then TMyComponent gets an
> OpRemove notification just before TMySubComponent is freed.  That's
> without using InsertComponent or RemoveComponent - is that what you
> meant?
> 
>       If you want to let other components on a form know of a
> component's impending demise, and those other components haven't been
> given FreeNotification from the component, then the form has to do the
> work (iterating through its components list to let the appropriate
> components know as required).  Hope that helps...
> 
>       Cheers,
> 
>       Carl Reynolds                      Ph: +64-9-4154790
>       CJN Technologies Ltd.             Fax: +64-9-4154791
>       [EMAIL PROTECTED]                DDI: +64-9-4154795
>       PO Box 302-278, North Harbour, Auckland, New Zealand
>       12 Piermark Drive, North Harbour Estate, Auckland, NZ
>       Visit our website at http://www.cjntech.co.nz/
> 
>       -----Original Message-----
>       From:   Myles Penlington [SMTP:[EMAIL PROTECTED]]
>       Sent:   Tuesday, July 06, 1999 11:53 AM
>       To:     Multiple recipients of list delphi
>       Subject:        [DUG]:  Notification Bug on Remove???
> 
>       What's your understanding of the Delphi Notification mechanism??
> 
>       My understanding is that if a TComponent or its descendant is
> removed from a Form then all other components on the Form will be sent
> a Notification (  MyComponent, OpRemove) - of course its owner is the
> form - this all stuff in the DFM.
> 
>       However this appears to be NOT the case. No OpRemove
> notification sent is if the component being removed is descended from
> TComponent eg TQuery etc - It does work if you remove a TControl or
> TWinControl.
> 
>       e.g. If you put a TButton , TDatabase and a TQuery on a form (in
> that order), the TDatabase does not get notified of the destruction of
> the TQuery - not that it matters in this case (but we have other cases
> that do matter - our own components).
> 
>       The offending code is in TComponent. 
> 
>       procedure TComponent.DestroyComponents; // This is called from
> TComponent.Destroy 
>       var
>         Instance: TComponent;
>       begin
>         while FComponents <> nil do
>         begin
>           Instance := FComponents.Last;
>           Remove(Instance); // IF THIS WAS RemoveComponent then all
> would be okay, or if TComponent.Remove did not set the owner to NIL.
>           Instance.Destroy;
>         end;
>       end;
> 
>       Do I have my understanding wrong or is this a serious bug/stuff
> up??
>       Can someone (Richard/Nic?) explain why it has been done this
> way??
>       By the way all the components do get a Notification( ,
> OpInsert), when they are created from the DFM, they just do not get
> the OpRemove when the form is destroyed, this occurs as
> TComponent.Create does a InsertComponent which does do a notification.
> 
>       Comments Please.
> 
>       Regards
> 
>       Myles Penlington
>       ADVANCED MANAGEMENT SYSTEMS
> 
>       
> ----------------------------------------------------------------------
> -----
>           New Zealand Delphi Users group - Delphi List -
> [EMAIL PROTECTED]
>                         Website: http://www.delphi.org.nz

application/ms-tnef

Reply via email to