1

Delphi アプリケーションは「遅延読み込み」を使用しており、実際に参照されるまでフォーム コンポーネントの読み込みを遅らせると聞いています。これは別の投稿で言及されていました。

これは Delphi で作成されたアプリケーションにも当てはまると思いますが、VCL ソースに遅延読み込みに関する記述が見当たらず、存在する場合は別の名前で呼ばれている可能性があります。

通常の使用では、アプリケーションが頻繁に起動されず、長時間実行される場合、実際に初めて使用するときに、起動時間を短縮して VCL コンポーネントの描画を高速化することが望ましい場合があります。

Delphi プログラマーはこれを制御できますか? (LazyLoad := false ;うまくいきませんでした;-)

4

1 に答える 1

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

これを実行すると、コンソール ウィンドウに次のように表示されます。

作成されたウィンドウ: Button1

各ページを順番に選択すると、コンソール ウィンドウに示すように、他のボタンが作成されます。

作成されたウィンドウ: Button1
作成されたウィンドウ: Button2
作成されたウィンドウ: 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;

フォームが最初に表示されると、コンソール ウィンドウに次のように表示されます。

作成されたウィンドウ: Button1
作成されたウィンドウ: Button2
作成されたウィンドウ: Button3

これは、Danny が言うように、ウィンドウは表示されるまで作成されないためです。

ここで、ページ コントロールに関するニュアンスは、ページの可視性の処理です。のコンストラクターには次がTTabSheet含まれます。

Visible := False;

さらに、 のVisibleプロパティは次のTTabSheetように公開されます。

property Visible stored False;

つまり、ページ コントロールが有効になると、そのページは非表示になり、VCL でVisible等しいという意味になりFalseます。Danny が言ったように、ウィンドウ コントロールは、コントロールが表示されるときに最初に作成されます。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すると実行され、ウィンドウハンドルが作成されますTrueTWinControl.UpdateShowing

そのため、フォームの作成時にすべてのページを表示するという上記のトリックは、あなたが望む効果をもたらします。

さて、上記のすべては非常にページ制御中心です。他の多くのコントロールでは、コントロールが表示されている場合、フォームの作成時にウィンドウが最初に作成されます。特定のフォームに特定の問題がある場合は、具体的な詳細を共有することをお勧めします。

于 2015-11-15T09:23:30.630 に答える