1

I've heard that the Delphi application uses "lazy loading", deferring the loading of form components until they are actually referenced. It was mentioned in another post - "That's why we changed TPageControl to be lazy-load - the Delphi IDE's options dialog was taking too long to load!"

I assume this applies to applications created with Delphi as well, but I can't find any mention of lazy loading in the VCL sources, suggesting maybe it's called something else if it does exist.

In cases where in normal use an application is started infrequently and runs for a long time, it might be desirable to forgo a faster startup time and have faster painting of VCL components when they are actually used for the first time.

Does the Delphi programmer have any control over this? (LazyLoad := false ; didn't work ;-)

Community
  • 1
  • 1
rossmcm
  • 5,493
  • 10
  • 55
  • 118
  • Read Danny Thorpe's answer more carefully in the link posted. It refers to a *specific control* (TPageControl) and modified behavior. It does not say anything about the *Delphi application*. Even the portion you (inaccurately) quoted says *TPageControl* and not *Delphi applications in general*. The *lazy loading* for Delphi applications in general is not creating forms until you need them (IOW, don't use autocreated forms). Do you have a *specific* problem you're trying to solve? – Ken White Nov 15 '15 at 03:16
  • @Ken Danny was talking about VCL on demand window creation. – David Heffernan Nov 15 '15 at 06:51
  • @ross I'm not aware of on demand VCL window creation being an issue. Do you have an example? – David Heffernan Nov 15 '15 at 06:52
  • @David: No, Danny was talking about on-demand TPageControl creation. In fact, he mentions it specifically three separate times in the linked answer. Nowhere in his post does he mention *VCL on demand window creation*. Perhaps you're reading a different post than the one linked? – Ken White Nov 15 '15 at 07:04
  • @Ken I don't think I'm reading a different post. Danny says, for instance, *The page window handles will be created when they are first shown.* – David Heffernan Nov 15 '15 at 07:12
  • @DavudL Yes, the *page windows* for the *TPageControl* (that I've specifically cited multiple times, as did Danny in his post. – Ken White Nov 15 '15 at 07:13
  • @Ken Looks like I'm am reading something different then. I'm reading http://stackoverflow.com/a/3242427/505088 and nowhere does it say "TPageControl and not Delphi applications in general". The post I was reading says "Normally, VCL controls don't create their window handle until it is actually needed - when it's actually shown, for example." – David Heffernan Nov 15 '15 at 07:34
  • @David: http://stackoverflow.com/a/3242427/62576 is what I quoted, and my specific comment was that it did **NOT** say *Delphi applications in general*. Respectfully, you should go back and re-read what I wrote again; you seem to have missed the entirety of it's meaning and intent. The lined answer by Danny specifically mentions only `TPageControl` (multiple times), which is what I've said since my first comment. – Ken White Nov 15 '15 at 08:03
  • @Ken I read Danny's answer very differently from you. *Normally, VCL controls don't create their window handle until it is actually needed - when it's actually shown, for example.* – David Heffernan Nov 15 '15 at 08:10
  • What are we talking about here: loading a form or creating a window handle? – Uwe Raabe Nov 15 '15 at 09:19
  • @Ken FWIW, window handles are typically first created in `TWinControl.UpdateShowing`. The special treatment is the setting of `Visible` to `False` in `TTabSheet.Create`. Then when a page first becomes active it is made visible. I'll expand on this in my answer. – David Heffernan Nov 15 '15 at 09:28
  • @Ken So it's a general fact that windows are created when the control is shown. But the specific is that pages are not shown until they are activated. That's what is special about them, and can be seen in the bespoke treatment of Visible for tab sheets. I believe that's what you were getting at and now I understand. – David Heffernan Nov 15 '15 at 10:22

1 Answers1

5

Consider the following simple demonstration project:

Project1.dpr

program Project1;

uses
  Vcl.Forms,
  Unit1 in 'Unit1.pas' {Form1};

{$R *.res}

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

Unit1.pas

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls, Vcl.StdCtrls;

type
  TButton = class(Vcl.StdCtrls.TButton)
  protected
    procedure CreateWnd; override;
  end;

  TForm1 = class(TForm)
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    TabSheet2: TTabSheet;
    TabSheet3: TTabSheet;
    Button1: TButton;
    Button2: TButton;
    Button3: TButton;
    procedure FormCreate(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TButton.CreateWnd;
begin
  inherited;
  Writeln('Window created: ' + Name);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  AllocConsole;
end;

end.

Unit1.dfm

object Form1: TForm1
  Caption = 'Form1'
  ClientHeight = 299
  ClientWidth = 635
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object PageControl1: TPageControl
    Left = 40
    Top = 40
    Width = 537
    Height = 233
    ActivePage = TabSheet1
    object TabSheet1: TTabSheet
      Caption = 'TabSheet1'
      object Button1: TButton
        Caption = 'Button1'
      end
    end
    object TabSheet2: TTabSheet
      Caption = 'TabSheet2'
      object Button2: TButton
        Caption = 'Button2'
      end
    end
    object TabSheet3: TTabSheet
      Caption = 'TabSheet3'
      object Button3: TButton
        Caption = 'Button3'
      end
    end
  end
end

When you run this, the console window says:

Window created: Button1

As you select each page in turn, the other buttons are created, as shown in the console window:

Window created: Button1
Window created: Button2
Window created: Button3

Now change the OnCreate event handler to force each page to be visible when the form is created:

procedure TForm1.FormCreate(Sender: TObject);
var
  i: Integer;
begin
  AllocConsole;

  for i := 0 to PageControl1.PageCount-1 do begin
    PageControl1.Pages[i].Visible := True;
  end;
end;

Now when the form is first shown, the console window reads:

Window created: Button1
Window created: Button2
Window created: Button3

This is because, as Danny says, the windows are not created until they are shown.

Now, the nuance with regards page controls is the handling of visibility of the pages. The constructor of TTabSheet contains this:

Visible := False;

Further, the Visible property of TTabSheet is published like this:

property Visible stored False;

That means that when a page control starts its life, its pages are hidden, in the VCL sense of having Visible equal to False. As Danny said, window controls are first created when a control is shown. That happens inside TWinControl.UpdateShowing which begins like this:

procedure TWinControl.UpdateShowing;
var
  ShowControl: Boolean;
  I: Integer;
begin
  ShowControl := (FVisible and (not (csDesigning in ComponentState) or not (csDesignerHide in ControlState)) or
    ((csDesigning in ComponentState) and not (csDesignerHide in ControlState)) and
    not (csNoDesignVisible in ControlStyle)) and
    not (csReadingState in ControlState) and not (csDestroying in ComponentState);
  if ShowControl then
  begin
    if WindowHandle = 0 then CreateHandle; // <-- this is the key
    if FWinControls <> nil then
      for I := 0 to FWinControls.Count - 1 do
        TWinControl(FWinControls[I]).UpdateShowing;
  end;
  ....
end;

The pages start out not showing, and then when they become active in TPageControl.ChangeActivePage the following is executed for the newly active page:

Page.BringToFront;
Page.Visible := True;

Setting Visible to True results in TWinControl.UpdateShowing executing, and the window handle being created.

And that's why the trick above of making all the pages visible at form creation time has the effect you desire.

Now, all of the above is very page control centric. For many other controls, the window is first created when the form is created, if the control is visible. If you a specific problem with a specific form then it would be best to share the specific details.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490