Delphi - 是否可以禁用 Delphi 的表单延迟加载?
Delphi - is it possible to disable Delphi's lazy loading of forms?
我听说 Delphi 应用程序使用 "lazy loading",推迟加载表单组件,直到它们被实际引用。它在 another post - "That's why we changed TPageControl to be lazy-load - the Delphi IDE's options dialog was taking too long to load!"
中被提及
我假设这也适用于使用 Delphi 创建的应用程序,但我在 VCL 源代码中找不到任何关于延迟加载的提及,这表明如果它确实存在,它可能被称为其他名称。
如果在正常使用中应用程序很少启动并运行很长时间,可能需要放弃更快的启动时间并在第一次实际使用时更快地绘制 VCL 组件。
Delphi 程序员对此有任何控制吗? (LazyLoad := false ;
无效 ;-)
考虑以下简单的演示项目:
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
当你运行这个时,控制台window说:
Window created: Button1
随着你select每个页面的依次创建,其他按钮被创建,如控制台所示window:
Window created: Button1
Window created: Button2
Window created: Button3
现在更改 OnCreate
事件处理程序以强制每个页面在创建表单时可见:
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;
现在,当表单首次显示时,控制台 window 显示:
Window created: Button1
Window created: Button2
Window created: Button3
这是因为,正如 Danny 所说,windows 在显示之前不会被创建。
现在,关于页面控件的细微差别是对页面可见性的处理。 TTabSheet
的构造函数包含:
Visible := False;
另外,TTabSheet
的Visible
属性是这样发布的:
property Visible stored False;
这意味着当一个页面控件开始它的生命时,它的页面是隐藏的,在 VCL 意义上 Visible
等于 False
。正如 Danny 所说, window 控件是在显示控件时首先创建的。这发生在 TWinControl.UpdateShowing
里面,它的开头是这样的:
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;
页面开始不显示,然后当它们在 TPageControl.ChangeActivePage
中激活时,将对新激活的页面执行以下操作:
Page.BringToFront;
Page.Visible := True;
将 Visible
设置为 True
会导致 TWinControl.UpdateShowing
执行,并创建 window 句柄。
这就是为什么上面在创建表单时使所有页面可见的技巧具有您想要的效果的原因。
现在,以上所有内容都是以页面控件为中心的。对于许多其他控件,如果控件可见,则在创建表单时首先创建 window。如果您对特定表格有特定问题,那么最好分享具体细节。
我听说 Delphi 应用程序使用 "lazy loading",推迟加载表单组件,直到它们被实际引用。它在 another post - "That's why we changed TPageControl to be lazy-load - the Delphi IDE's options dialog was taking too long to load!"
中被提及我假设这也适用于使用 Delphi 创建的应用程序,但我在 VCL 源代码中找不到任何关于延迟加载的提及,这表明如果它确实存在,它可能被称为其他名称。
如果在正常使用中应用程序很少启动并运行很长时间,可能需要放弃更快的启动时间并在第一次实际使用时更快地绘制 VCL 组件。
Delphi 程序员对此有任何控制吗? (LazyLoad := false ;
无效 ;-)
考虑以下简单的演示项目:
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
当你运行这个时,控制台window说:
Window created: Button1
随着你select每个页面的依次创建,其他按钮被创建,如控制台所示window:
Window created: Button1 Window created: Button2 Window created: Button3
现在更改 OnCreate
事件处理程序以强制每个页面在创建表单时可见:
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;
现在,当表单首次显示时,控制台 window 显示:
Window created: Button1 Window created: Button2 Window created: Button3
这是因为,正如 Danny 所说,windows 在显示之前不会被创建。
现在,关于页面控件的细微差别是对页面可见性的处理。 TTabSheet
的构造函数包含:
Visible := False;
另外,TTabSheet
的Visible
属性是这样发布的:
property Visible stored False;
这意味着当一个页面控件开始它的生命时,它的页面是隐藏的,在 VCL 意义上 Visible
等于 False
。正如 Danny 所说, window 控件是在显示控件时首先创建的。这发生在 TWinControl.UpdateShowing
里面,它的开头是这样的:
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;
页面开始不显示,然后当它们在 TPageControl.ChangeActivePage
中激活时,将对新激活的页面执行以下操作:
Page.BringToFront;
Page.Visible := True;
将 Visible
设置为 True
会导致 TWinControl.UpdateShowing
执行,并创建 window 句柄。
这就是为什么上面在创建表单时使所有页面可见的技巧具有您想要的效果的原因。
现在,以上所有内容都是以页面控件为中心的。对于许多其他控件,如果控件可见,则在创建表单时首先创建 window。如果您对特定表格有特定问题,那么最好分享具体细节。