2017-06-13 80 views
2

我已经注册为成分的TFrame的子类,我已经注意到,Loaded程序执行两次:加载程序

运行:

TMyFrame = class(TFrame) 
    private 
    protected 
    procedure Loaded(); override; 
    public 
    constructor Create(AOwner : TComponent); override; 
    end; 

constructor TMyFrame.Create(AOwner : TComponent); 
begin 
    ShowMessage('Before TMyFrame.Create'); 
    inherited Create(AOwner); 
    ShowMessage('After TMyFrame.Create'); 
end; 

procedure TMyFrame.Loaded(); 
begin 
    ShowMessage('Before TMyFrame.Loaded'); 
    inherited; 
    ShowMessage('After TMyFrame.Loaded'); 
end; 

设计时:

procedure Register; 
begin 
    RegisterComponents('Test', [TMyFrame]); 
end; 

输出:

在运行时,创建一个表单,其中有一个TMyFrame组件。

TMyFrame.Create

之前

之前TMyF​​rame.Loaded

后TMyFrame.Loaded

TMyFrame.Create

之前TMyF​​rame.Loaded

TMyFrame.Loaded后后

在设计时,就加入了TMyFrame到窗体:

TMyFrame.Create

之前

之前TMyF​​rame.Loaded

后TMyFrame.Loaded

TMyFrame.Create

在设计时,op付民的形式,其中有一个TMyFrame成分:

之前TMyF​​rame.Create

TMyFrame.Loaded

之前

后TMyFrame.Loaded

后TMyFrame.Create

之前TMyFrame.Loaded

TMyFrame.Loaded

为什么Loaded过程被执行两次?如何避免这种情况?

+0

如果使用调试DCU进行编译,您可以设置断点并查看调用堆栈。 –

+0

*当*看到这些信息时?在IDE中?或在运行时?如果在IDE中您并不在意,那么可以使用针对componentstate = csDesigning的测试来包围消息。 – Dsm

+0

@Dsm:“在运行时向表单添加TMyFrame后”。 –

回答

7

此行为是按设计的。

Loaded

加载可以在遗传形式的多次调用。在每次继续传输继承级别时,它都被称为 。不要在重写的Loaded方法中分配 内存,而不必先检查是否在先前的调用中分配了内存 。

+0

你知道一种区分上次执行的方法吗? (在本质上,我想使用一些在构造函数中初始化的变量) – ExDev

+0

不可能。最可能最安全的事情是将代码从'Loaded'移动到'AfterConstruction'。 –