破坏期间的VCL事件

时间:2011-03-09 10:55:47

标签: delegates destructor c++builder vcl

我遇到一个问题,某些VCL控件偶尔会在被销毁时触发事件,导致处理程序以已被销毁的子类形式被调用(例如,控件被父类的析构函数杀死TForm。)

这是否属于(第三方)控件的违约,我是否应该使用“if(open)”警卫丢弃每个事件处理程序,或者是否应该由其他机制处理。我或许天真地假设__published闭包会自动取消注册,有点类似于常规虚函数的工作方式。

2 个答案:

答案 0 :(得分:2)

你的越野车控件是否正确设置了“所有者”属性?默认情况下,表单拥有其上的所有控件,其“Owner”属性指向TForm实例,此表单负责释放所有拥有的控件。如果您通过IDE表单设计器设计表单,那就是这样的方式。如果手动创建控件,则必须通过构造函数提供“Owner”属性。检查您是否将正确的表格作为“所有者”传递。此外,如果你有自定义控件的源代码,建立在TControl的顶部,检查它们的构造函数是否正确地将“Owner”属性传递给底层的TControl构造函数。

答案 1 :(得分:1)

__published闭包不能保证那种,闭包只是一个指向类实例和函数的指针。然而,VCL还有其他机制。

通常,在开发依赖于其他组件的组件时,这是一种很好的做法,以确保在删除组件时清除对组件的任何内部引用。在VCL中,可以通过TComponent中的免费通知来实现此目的。

如果您所依赖的组件具有不同的所有者且不在表单上,​​则必须注册您的组件才能接收这些通知。您可以通过FreeNotification功能执行此操作(请记住,在删除通知的组件时,请再次注销组件,以便进行此项使用RemoveFreeNotification)。每当控件添加到与此组件相同的表单(或所有者)时,将调用函数Notification,并引用添加或删除的组件以及执行的操作。

所以你只需覆盖Notification函数,记得也要调用父函数。重载函数可能如下所示:

void __fastcall TMyComponent::Notification(TComponent* AComponent, TOperation Operation)
{
    if (Operation == opRemove && AComponent == interestingComponent)
    {
        this->interestingComponent = NULL;
    }

    inherited::Notification(AComponent, Operation);
}

如果这是第三方控件,他们当然应该确保这一点并确保有dangling pointers,因为组件被释放,如果由于某种原因忘记了你必须添加该功能,要么通过子类化或通过重置您所述的事件。如果这是你自己的组件,那么你应该确保这样做。