就在我的 TCustomWinControl
被永久销毁之前,我需要对其句柄执行一些操作。
如果我尝试在析构函数
中访问其句柄,则会收到错误:
"Control "xxx" has no parent window".
那么 TWinControl 析构函数之前的最后一个阶段是什么?其句柄 (HandleAllocation
) 仍然有效?
type
TPanel = class(ExtCtrls.TPanel)
protected
procedure DestroyWindowHandle; override;
public
procedure BeforeDestruction; override;
end;
procedure TPanel.DestroyWindowHandle;
begin
Beep;
if csDestroying in ComponentState then Beep;
inherited;
end;
procedure TPanel.BeforeDestruction;
begin
if HandleAllocated then Beep;
inherited;
end;
没有蜂鸣声。
最佳答案
更新
这比我最初想象的要复杂。你的控件存在于一个窗体上,控件的死亡是由该窗体的死亡引起的。当窗体被销毁时,子窗口也会被销毁。因此,Win32 API 负责销毁您的窗口。 VCL 通过响应 WM_NCDESTROY
消息来跟踪这一点:
procedure TWinControl.WMNCDestroy(var Message: TWMNCDestroy);
begin
inherited;
FHandle := 0;
FShowing := False;
end;
所以,我想你可以自己处理WM_NCDESTROY
。在 ControlState
中查找 csRecreating
,根据窗口销毁是否与 VCL 窗口重新创建相关来切换行为。
这里需要注意的一个有趣的点是,没有理由必须调用控件的析构函数。如果它不属于表单,那么您的控件将不会被破坏。然后您可以将其重新设置为另一个表单的父级。所以 WM_NCDESTROY
确实是正确的钩子(Hook)。
原始答案
析构函数的源代码如下所示:
destructor TWinControl.Destroy;
var
I: Integer;
Instance: TControl;
begin
Destroying;
if FDockSite then
begin
FDockSite := False;
RegisterDockSite(Self, False);
end;
FDockManager := nil;
FDockClients.Free;
if Parent <> nil then RemoveFocus(True);
if FHandle <> 0 then DestroyWindowHandle;
I := ControlCount;
while I <> 0 do
begin
Instance := Controls[I - 1];
Remove(Instance);
Instance.Destroy;
I := ControlCount;
end;
FBrush.Free;
{$IFDEF LINUX}
if FObjectInstance <> nil then WinUtils.FreeObjectInstance(FObjectInstance);
{$ENDIF}
{$IFDEF MSWINDOWS}
if FObjectInstance <> nil then Classes.FreeObjectInstance(FObjectInstance);
{$ENDIF}
inherited Destroy;
end;
对 Win32 API DestroyWindow
的调用是在这一行中进行的:
if FHandle <> 0 then DestroyWindowHandle;
所以你需要在此之前运行你的代码。
您可以重写DestroyWindowHandle
并在那里完成您的工作。只要您需要处理的事件是窗口的破坏,那么这种方法就可以很好地工作。但请记住,重新创建窗口时将调用 DestroyWindowHandle
。
如果您需要执行与 VCL 控件销毁相关的操作,那么您最好重写 BeforeDestruction
。或者作为替代方案,您可以重写 DestroyWindowHandle
并在 ComponentState
中测试 csDestroying
。
关于delphi - TWinControl - 当 WinControl 具有有效句柄时,析构函数之前的最后一个阶段是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27038925/