我听说Delphi应用程序使用“延迟加载”,推迟加载表单组件,直到实际引用它们为止。在another post中提到 - “这就是我们将TPageControl更改为延迟加载的原因 - Delphi IDE的选项对话框加载时间太长了!”
我认为这也适用于使用Delphi创建的应用程序,但我在VCL源代码中找不到任何延迟加载的提及,这表明如果确实存在,可能会将其称为其他内容。
在正常使用情况下,应用程序不经常启动并运行很长时间,可能需要放弃更快的启动时间,并在第一次实际使用时更快地绘制VCL组件。
Delphi程序员对此有何控制权? (LazyLoad := false ;
没有用;-)
答案 0 :(得分:5)
考虑以下简单的演示项目:
<强> 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 created: Button1
当你依次选择每个页面时,会创建其他按钮,如控制台窗口所示:
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 created: Button1 Window created: Button2 Window created: Button3
这是因为,正如Danny所说,窗口在显示之前不会被创建。
现在,关于页面控件的细微差别在于处理页面的可见性。 TTabSheet
的构造函数包含:
Visible := False;
此外,Visible
的{{1}}属性发布如下:
TTabSheet
这意味着当页面控件开始生命时,其页面将被隐藏,在VCL意义上property Visible stored False;
等于Visible
。正如Danny所说,当控件显示时,首先会创建窗口控件。这发生在False
内部,如下所示:
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
执行,并且正在创建窗口句柄。
这就是为什么在表单创建时使所有页面可见的上述技巧会产生你想要的效果。
现在,以上所有内容都是以页面控制为中心的。对于许多其他控件,如果控件可见,则在创建表单时首先创建窗口。如果您遇到特定表格的特定问题,那么最好分享具体细节。