我遇到一个问题,某些VCL控件偶尔会在被销毁时触发事件,导致处理程序以已被销毁的子类形式被调用(例如,控件被父类的析构函数杀死TForm。)
这是否属于(第三方)控件的违约,我是否应该使用“if(open)”警卫丢弃每个事件处理程序,或者是否应该由其他机制处理。我或许天真地假设__published闭包会自动取消注册,有点类似于常规虚函数的工作方式。
答案 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,因为组件被释放,如果由于某种原因忘记了你必须添加该功能,要么通过子类化或通过重置您所述的事件。如果这是你自己的组件,那么你应该确保这样做。