2012-04-02 27 views
-1

我正在Delphi5工作在组件/表单销毁之前是否可以显示表单?

我想在组件在项目运行时被销毁之前出现一个自定义窗体。

是否可以在自定义组件中执行此操作?换句话说,我可以在定制组件在运行时被销毁之前显示表单吗?当它被放置的表单被关闭时?

我试图把下面的组件的析构函数,但我得到一个访问冲突错误时,窗体被关闭:

destructor TqqFormLogger.Destroy; 
begin 
    if NOT (csDesigning in ComponentState) then 
    SurveyForm.Click; 

    inherited Destroy; 
end; 
+2

做你正在做的事情没有问题。不可能说为什么它不适合你。什么是SurveyForm?任何更多代码的机会,所以我们可以看到AV在哪里。 – 2012-04-02 21:11:49

+0

对不起,没有那么清楚。我所拥有的是一个名为“FormLogger”的组件,它放置在我们项目的所有表单上。在项目运行时,该组件会创建一个TButton(称为SurveyButton),如果单击它,将打开一个表单(SurveyForm)。到目前为止,这部分工作正常。但是,我们希望每次关闭表单时都打开SurveyForm(即触发SurveyButton.Click事件)。这似乎是SurveyButton时。点击是在我的组件的析构函数中触发的,承载组件的主窗体已经被销毁。有解决方案吗?谢谢 – user1202134 2012-04-05 14:42:31

+0

表单自动调用设计时组件上的FreeNotification()(它依次调用窗体的FreeNotification()方法)。您的组件可以覆盖它的'Notification()'方法来检测表单何时被释放。或者,如果您有任何在关闭时没有立即释放的表单,则您的组件的构造函数可以将事件处理程序分配给表单的“OnClose”事件。 – 2012-04-05 16:04:16

回答

0

看一看重写BeforeDestruction()方法,而不是析构函数。

但是为什么在组件层?为什么不在父窗体的OnClose事件中执行?

+1

这为什么会有所作为?推测问题是SurveyForm不好。这就是BeforeDestruction,OnClose等的情况。 – 2012-04-02 21:37:11

+0

'BeforeDestruction()'在任何析构函数之前被调用,所以它是一个好的地方,在它的析构函数(特别是隐含的析构函数)有机会触及任何东西。但更重要的是,在窗体的任何子控件开始销毁之前触发父窗体的OnClose事件,所以这可能是一个计时问题,在父窗体关闭后但在TqqFormLogger之前,“SurveyForm”被释放销毁。 – 2012-04-02 22:38:40

+0

为了简化我的问题:是否有可能有组件控制或中断它的父(所有者)窗体的关闭事件(销毁)过程,以便在窗体关闭之前对其自己进行一些处理? – user1202134 2012-04-05 15:36:20

1

一般来说,AV是某些代码试图调用一个不再存在的东西的例程的信号。

从这个角度看,一个AV为这个特定的析构函数的结果可能表明两种情况之一:

  1. SurveyForm不存在了,或者
  2. 代码为SurveyForm.Click结果预计将组件的存在,以是真的,但组件无论如何都会被销毁。

名称Click暗示SurveyForm是一个按钮式控件。如果该控件不是你的组件的一部分,而是组件所在表单的一部分,那么前者(情况1)当然可以是真的:表单的析构函数已经销毁了SurveyForm,现在即将销毁你的组件。你可以通过使用BeforeDestruction来防止这种情况,正如雷米已经提到的那样。另外(但只是一般性的提示,而不是解决你的问题),你可以通过注册该组件给你自己来通知它的销毁,从而防止使用被销毁的组件。与FreeNotification结合覆盖Notification为此在你无组件:

procedure TqqFormLogger.SetSurveyForm(Value: TForm); 
begin 
    FSurveyForm := Value; 
    FSurveyForm.FreeNotification(Self); 
end; 

procedure TqqFormLogger.Notification(AComponent: TComponent; 
    Operation: TOperation); 
begin 
    inherited Notification(AComponent, Operation); 
    if (AComponent = FSurveyForm) and (Operation = opRemove) then 
    FSurveyForm := nil; 
end; 

destructor TqqFormLogger.Destroy; 
begin 
    if FSurveyForm <> nil then 
    ... 

如果控制确实是你的组件的一部分,那么我怀疑背后Click代码允许组件的析构函数的过程使用无论如何(案2)。例如,在发布消息(手动或由于VCL或Windows内部结果)时,将在消息驱动或处理之前调用inherited Destroy

简而言之:现在的问题太笼统了,无法给出具体的答案。

+0

'SurveyForm'仍然会在'Click'方法被调用的地方生存,因为它在'TComponent.Destroy'执行之前不会死亡。 – 2012-04-02 22:38:01

+0

+1任何时候一个组件都有一个对外部组件的引用,如果外部组件过早或乱序释放,使用'FreeNotification()'是个好主意。 – 2012-04-02 22:41:32

+0

@DavidHeffernan:但我们还不知道何时/何地调用了与TqqFormLogger.Destroy相关的SurveyForm.Destroy,或者即使SurveyForm与TqqFormLogger的父表单相同。 – 2012-04-02 22:42:36

相关问题