如何在Delphi中的TFrame上模拟OnDestroy事件? [英] How to simulate an OnDestroy event on a TFrame in Delphi?

查看:291
本文介绍了如何在Delphi中的TFrame上模拟OnDestroy事件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在Delphi中为TFrame模拟OnDestroy事件?

How can i simulate an OnDestroy event for a TFrame in Delphi?

我认真地在框架中添加了constructordestructor,以为TForm会这样做:

i nievely added a constructor and destructor to my frame, thinking that is what TForm does:

TframeEditCustomer = class(TFrame)
...
public
   constructor Create(AOwner: TComponent); override;
   destructor Destroy; override;
   ...
end;

constructor TframeEditCustomer.Create(AOwner: TComponent)
begin
    inherited Create(AOwner);

    //allocate stuff
end;

destructor TframeEditCustomer.Destroy;
begin
   //cleanup stuff

   inherited Destroy;
end;

问题是当我的析构函数运行时,框架上的控件已被破坏并且不再有效.

The problem with this is that by the time my destructor runs, controls on the frame have been destroyed and are no longer valid.

其原因在于包含窗体的析构函数,该析构函数用于引发OnDestroy事件:

The reason for this is in the containing form's destructor, which it uses to fire an OnDestroy event:

destructor TCustomForm.Destroy;
begin
   ...
   if OldCreateOrder then DoDestroy; //-->fires Form's OnDestroy event; while controls are still valid
   ...
   if HandleAllocated then DestroyWindowHandle; //-->destroys all controls on the form, and child frames
   ...
   inherited Destroy; //--> calls destructor of my frame
   ...
end;

当窗体的析构函数运行时,将调用我的框架对象的析构函数.问题在于,为时已晚.表单调用DestroyWindowHandle,它要求Windows销毁表单的窗口句柄.这会递归地破坏所有子窗口-包括我框架中的子窗口.

The destructor of my frame object is being called when the form's destructor runs. Problem with this is that it's too late. The form calls DestroyWindowHandle, which asks Windows to destroy the form's window handle. This recursively destroys all child windows - including those on my frame.

因此,当我的框架的destructor运行时,我尝试访问不再处于有效状态的控件.

So when my frame's destructor runs, i attempt to access controls that are no longer in a valid state.

如何在Delphi中为TFrame模拟OnDestroy事件?

How can i simulate an OnDestroy event for a TFrame in Delphi?

  • Simulating OnCreate and OnDestroy for a Frame?
  • How to Implement the OnCreate event for a Delphi TFrame object
  • Embargadero QC#1767: TFrame misses OnCreate, OnDestroy, OnShow

推荐答案

您需要添加一个WM_DESTROY处理程序,并在ComponentState中检查csDestroying,以便仅在实际销毁时才捕获它,而在重新创建句柄时才捕获它.

You need to add a WM_DESTROY handler and check for csDestroying in the ComponentState so it's only caught when actually destroying, and not when recreating the handle.

type
  TCpFrame = class(TFrame)
  private
    FOnDestroy: TNotifyEvent;
    procedure WMDestroy(var Msg: TWMDestroy); message WM_DESTROY;
  published
    property OnDestroy: TNotifyEvent read FOnDestroy write FOnDestroy;
  end;

procedure TCpFrame.WMDestroy(var Msg: TWMDestroy);
begin
  if (csDestroying in ComponentState) and Assigned(FOnDestroy) then
    FOnDestroy(Self);
  inherited; 
end;

这仅在框架的窗口句柄已实际创建时才起作用.没有另一个很好的挂钩点,因此,如果要确保始终调用它,则需要在WMDestroy中设置一个标志,如果未命中,则应在析构函数中调用它.

That will only work if the frame's window handle has actually been created. There isn't another good hook point, so if you want to ensure it's always called you'll need to set a flag in WMDestroy and fall back to calling it in the destructor if that isn't hit.

窗口句柄本身全部在WM_NCDESTROY中清除,在所有后代WM_DESTROY消息返回之后调用该窗口句柄,因此该窗体及其所有子句柄在这一点上仍然有效(忽略任何在WM_DESTROY消息中释放的句柄).表单的OnDestroy).

The window handles themselves are all cleared in WM_NCDESTROY, which is called after all of the descendant WM_DESTROY messages return, so the form and all of its childens' handles should still be valid at this point (ignoring any that were freed in the form's OnDestroy).

这篇关于如何在Delphi中的TFrame上模拟OnDestroy事件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆