控件编程-Notification

组件原码

procedure TComponent.Notification(AComponent: TComponent;
  Operation: TOperation);
var
  I: Integer;
begin
  if (Operation = opRemove) and (AComponent <> nil) then
    RemoveFreeNotification(AComponent);                 // 移除释放通知                
  if FComponents <> nil then               // 还有组件
  begin
    I := FComponents.Count - 1;    
    while I >= 0 do    //  这个循环很不好理解,艾老师,您能帮解释一下吗?
    begin
      TComponent(FComponents[I]).Notification(AComponent, Operation);    // 这里应该是调用了递归
      Dec(I);                                                            // 去通知这个组件包含的组件   
      if I >= FComponents.Count then            // 为什么要减 1 呢
        I := FComponents.Count - 1;             // 由 dec(i) 来控制不就行了吗?
    end;
  end;
end;
//---------------------------------------
  在移除组件中
procedure TComponent.RemoveNotification(AComponent: TComponent);
begin
  if FFreeNotifies <> nil then
  begin
    FFreeNotifies.Remove(AComponent);
    if FFreeNotifies.Count = 0 then
    begin
      FFreeNotifies.Free;
      FFreeNotifies := nil;
    end;
  end;
end;

procedure TComponent.RemoveFreeNotification(AComponent: TComponent);
begin
  RemoveNotification(AComponent);                    // 已经把这个组件给移除了,而下句怎么还用它来通知呢?
  AComponent.RemoveNotification(Self);
end;
 

解答:

procedure TComponent.Notification(AComponent: TComponent;
  Operation: TOperation);
var
  I: Integer;
begin
  if (Operation = opRemove) and (AComponent <> nil) then
    RemoveFreeNotification(AComponent);                 // 移除释放通知                
  if FComponents <> nil then               // 还有组件
  begin
    I := FComponents.Count - 1;    
    while I >= 0 do    //  这个循环很不好理解?
    begin
      TComponent(FComponents[I]).Notification(AComponent, Operation);    // 这里应该是调用了递归

//准确的说不是递归,只是可能会多次调用不同组件的同名函数

      Dec(I);                                                            // 去通知这个组件包含的组件   
      if I >= FComponents.Count then            // 为什么要减 1 呢
        I := FComponents.Count - 1;             // 由 dec(i) 来控制不就行了吗?
      
      //Notification函数是一个函数,一个可重写的虚函数,谁能保证程序员在里面写什么代码呢?
      //假定某个程序员在重写这个函数的时候释放了一个FComponents列表中的一个组件呢?
      //这时实际上仅仅是一个dec(i),i就可能会大于FComponents.Count,下一个循环就有可能下标溢出。
      

    end;
  end;
end;

//---------------------------------------

//这里并不是移除组件的方法,而只是移除其他组件在自己注册的“移除通知”,
//也就是说自己有什么事情的时候将不再通知AComponent了。

procedure TComponent.RemoveNotification(AComponent: TComponent);
begin
  if FFreeNotifies <> nil then
  begin
    FFreeNotifies.Remove(AComponent);
    if FFreeNotifies.Count = 0 then
    begin
      FFreeNotifies.Free;
      FFreeNotifies := nil;
    end;
  end;
end;

procedure TComponent.RemoveFreeNotification(AComponent: TComponent);
begin
  RemoveNotification(AComponent);

  //AComponent很显然还没有被删除,要知道代码是顺序执行的,组件可能正在被删除,但是还没有被删除,
  //而下面的一句也只是让AComponent去除自己(Self)注册的一个“移除通知”,
  //也就是说让AComponent将来被释放的时候将不用通知自己了(self),因为自己马上就要被释放了

  AComponent.RemoveNotification(Self);
end;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值