如何在Delphi中为 TFrame
模拟 OnDestroy
事件?
我简单地在我的框架中添加了 constructor
和 destructor
,认为这是 TForm
的作用:
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;
这个问题是,当我的析构函数运行时,框架上的控件已经被破坏并且不再有效 .
原因在于包含表单的析构函数,它用于触发 OnDestroy
事件:
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;
当表单's destructor runs. Problem with this is that it'太迟时,我的框架对象的析构函数被调用 . 该表单调用 DestroyWindowHandle
,要求Windows销毁表单的窗口句柄 . 这会递归地破坏所有子窗口 - 包括我框架上的窗口 .
因此,当我的框架 destructor
运行时,我尝试访问不再处于有效状态的控件 .
如何在Delphi中为 TFrame
模拟 OnDestroy
事件?
4 回答
您需要添加WM_DESTROY处理程序并检查ComponentState中的csDestroying,以便它仅在实际销毁时捕获,而不是在重新创建句柄时捕获 .
这只有在实际创建了框架的窗口句柄时才有效 . 没有其他好的挂钩点,所以如果你想确保它总是被调用,你需要在WMDestroy中设置一个标志,如果没有被击中则回退到在析构函数中调用它 .
窗口句柄本身都在WM_NCDESTROY中被清除,WM_NCDESTROY在所有后代WM_DESTROY消息返回后被调用,因此表单及其所有childens的句柄在此时仍然有效(忽略在表单的OnDestroy中释放的任何内容) .
听起来更像
OnClose
而不是OnDestroy
.无论如何,我只是从基础祖先继承了我的所有框架和表单,然后表单的onclose调用组件层次结构中的所有框架 .
(这只是一个想法,但我现在没有时间来构建一个概念证明,但我会分享它:)
如果's a problem with the Windows handle(s), you should check wether you'能够附加Windows ' event callback pointer that gets called when the frame'的Windows句柄不再存在 . 也许像RegisterWaitForSingleObject这样的功能
另一种选择是覆盖
AfterConstruction
和BeforeDestruction
像这样的东西: