I expect to see fully initialized UI with a label showing "Data is not loaded", then after 5 seconds "Data is loaded".
I've taken an example from there: What is the best way to autostart an action after OnShow event?
but I see nothing, and then only "Data is loaded", after the delay.
Code is listed below:
StartupAction.dpr
program StartupAction;
uses
  Vcl.Forms,
  MainForm in 'MainForm.pas' {Form1};
{$R *.res}
begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.
MainForm.dfm
object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 254
  ClientWidth = 635
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object lbl1: TLabel
    Left = 104
    Top = 40
    Width = 87
    Height = 13
    Caption = 'Data is not loaded'
  end
end
MainForm.pas
unit MainForm;
//Load data after full UI initialization
interface
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
  TForm1 = class(TForm)
    lbl1: TLabel;
  private const
    WM_STARTUP = WM_USER;
  protected
    procedure DoShow(); override;
  private
    procedure WMStartup(var Msg: TMessage); message WM_STARTUP;
    procedure _loadData();
  public
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.DoShow();
begin
  inherited;
  PostMessage(Handle, WM_STARTUP, 0, 0);
end;
procedure TForm1.WMStartup(var Msg: TMessage);
begin
  inherited;
  _loadData();
end;
procedure TForm1._loadData();
begin
  Sleep(5000);
  lbl1.Caption := 'Data is loaded';
end;
end.
The only solution that works to some extent is using of TTimer with 500 ms delay, but it is not a true solution.