Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi中Loaded()后调用什么_Delphi_Vcl - Fatal编程技术网

Delphi中Loaded()后调用什么

Delphi中Loaded()后调用什么,delphi,vcl,Delphi,Vcl,我有一些代码可以在Loaded()函数中设置内部对象。但是,有些外部对象尚未完全创建,而是在Loaded()函数完成后创建的。Delphi在调用Loaded()之后调用了什么函数 更好的是,组件的创建顺序是什么 基本上我有一个TCP服务器和客户端。大多数人会将这两个组件放在两个单独的应用程序中,有些人会将它们放在同一个应用程序中以供本地访问 我的客户机试图在onload()中从服务器获取数据,但服务器可能尚未启动!我想知道在调用了所有onload()之后是否调用了另一个函数。通常您会为此重写TO

我有一些代码可以在Loaded()函数中设置内部对象。但是,有些外部对象尚未完全创建,而是在Loaded()函数完成后创建的。Delphi在调用Loaded()之后调用了什么函数

更好的是,组件的创建顺序是什么

基本上我有一个TCP服务器和客户端。大多数人会将这两个组件放在两个单独的应用程序中,有些人会将它们放在同一个应用程序中以供本地访问


我的客户机试图在onload()中从服务器获取数据,但服务器可能尚未启动!我想知道在调用了所有onload()之后是否调用了另一个函数。

通常您会为此重写TObject.AfterConstruction

执行顺序为:

  each Component.AfterConstruction in creation order
(Form or DataModule).Loaded  
  each Component.Loaded in creation order
(Form or DataModule).AfterConstruction 
跟踪:

Debug Output: button AfterConstruction Process Project2.exe (4876)
Debug Output: Form Loaded Process Project2.exe (4876)
Debug Output: button Loaded Process Project2.exe (4876)
Debug Output: Form AfterConstruction Process Project2.exe (4876)

我不知道你对我是什么意思

服务器可能尚未启动

无论如何,如果客户机和服务器都在同一个应用程序窗体或数据模块上,我会看到替代方案:

  • 您可以“强制”系统在客户端之前创建服务器,并在服务器的OnLoad中启动服务器,然后在客户端OnLoad中启动服务器,因为:

    当流系统从表单文件加载表单或数据模块时,它首先通过调用其构造函数来构造表单组件,然后从表单文件读取其属性值。读取所有组件的所有属性值后,流媒体系统按照组件创建的顺序调用每个组件的加载方法。这使组件有机会初始化依赖于其他组件或其自身其他部分的值的任何数据

  • 在服务器启动时通知“客户机”,让其进行初始化(从服务器提取数据)。您可以使用直接方法调用、发布消息或任何您认为合适的方法

  • 让客户机在自己的OnLoad方法中支持服务器


  • 为什么不使用主窗体的onCreate事件

    Loaded在dfm流入后立即调用,不应用于访问服务器。您最好的选择可能是在构造函数中向自己发布一条自定义消息,并拥有一个响应该消息的消息处理程序过程。发布消息会将其放入消息队列的末尾,因此,在处理完前面的所有其他消息之前,不会对其进行处理。这将延迟足够长的时间,使您的组件能够完全构建以供使用

  • 我在一些组件中使用了断点,并确定AFTERCONSTRUCTION是在加载之前而不是之后调用的

  • 我也在表单上做了同样的事情,并坚定地认为加载后调用AFTERCONSTRUCTION,而不是加载前调用AFTERCONSTRUCTION

  • 请记住,后构造是TObject中的一种方法,但加载不是。因此,Loaded是由代码生成的,这些代码可能不一定按照与后构建相关的特定顺序排列,因为Loaded实际上不是TObject的构建序列的一部分,而后构建是

    事实上,如果您研究RTL源代码,您将看到Loaded甚至不是由TComponent的任何self.method调用的,而是由正在读取DFM的流读取器调用的,这很可能是在“所有者”组件的控制下发生的。因此,我强烈建议,其与后期施工的关系并没有得到真正的保证。它以表单的特定顺序出现的事实是,表单最有可能是启动流读取的组件。换言之,它有一种便利事故的味道,这种事故是在一种形式的后期施工之前发生的

    进一步的研究表明,包含以下代码的非表单组件可能永远不会调用事件处理程序

    procedure Txxx.AfterConstruction; override;
    begin
       inherited AfterConstruction;
       if Assigned(FOnCreate) then FOnCreate(Self);
    end;
    
    原因是,如果在加载属性之前调用AfterConstruction,将发现FOnCreate尚未分配

    在这种情况下,您确实必须使用以下方法:

    procedure Loaded; override;
    begin
       inherited Loaded;
       if assigned(OnLoaded) then OnLoaded(self);
    end;
    
    正如我所说,这将为表单拥有的组件产生不同于表单本身的结果!TForm组件通常是DFM流读取器的调用者,它是为从表单读取的每个组件调用加载的流读取器。这个过程(幸运的是)在表单的后构造之前开始,但是该读取器加载的每个组件都会在其加载方法之前调用其后构造方法

    QED

    最具讽刺意味的是,Delphi 6帮助文件中说“ToObject中实现的AfterConstruction方法不起任何作用。在创建对象后执行某些操作的类时重写此方法。例如,TCustomForm重写AfterConstruction以生成OnCreate事件。”

    它没有说的是,如果您在TCustomForm之外的任何东西上尝试此功能(TCustomForm已经这么做了),它将不起作用!因为在调用AfterConstruction之前,只有一个表单(已经有了它)才会加载它的OnCreate属性。任何其他组件都不会,因为表单调用的DFM读取器在加载之前调用AfterConstruction!Borland et.al.显然不理解自己的代码,或者至多编写一个帮助文件条目来暗示某些事情是可能的,而事实并非如此

    注意,如果您的组件不在表单上,并且是在运行时创建的(即使它是“拥有的”组件),则不会调用其“加载的”方法,因为不涉及流读取器

    另一个关注点是“Dr”Bob Swart不久前写的关于AfterConstruction的文章,即它表示可以调用虚拟方法的点。显然,这只是部分正确:如果表单的加载方法是在AfterConstruction之前调用的,那么您将无法调用任何虚拟me