お知らせ

電子会議

ライブラリ

パレット

Delphi FAQ検索

Delphi FAQ一覧

サンプル蔵





FDelphi FAQ
16番会議室「玉石混淆みんなで作るSample蔵」に寄せられたサンプル

"複数Formを丸ごとSave,Load"





 ユーザーが種々の設定や位置を変えてそれを保存し次回起動時に読み込んで
復帰するようなタイプのアプリケーションで便利に使える方法の紹介.

<使い方>
 SaveFormsをアプリ終了前に実行し,RestoreFormsをメインフォーム(こいつ
は普通のメインフォーム)のOnShowなどで呼び出せば全自動で複数フォームの
前回実行時そのままの状態が復元されます.
 ユーザーがいじったりする各種設定値は保存対象のFormの published property
などにしておけば自動で全部保存されます.

 アプリの初期状態では普通の Create でFormを生成しますが,デフォルト設定を
ユーザーが変えられるようにするには,変えた状態のFromだけ別に 
WriteComponentResFile で取っておき,CreateNew で生成してから
ReadComponentResFile で読み込めばよいでしょう.

 WriteComponentResFile と ReadComponentResFile を使えば,フォーム等を
ファイルに納めることは簡単に出来ますが,複数のフォームをひとつのファイル
に出し入れすることは出来ません.
 保存復帰の対象となるFormはすべて実行時に動的に生成しますが,こいつらの
Ownerとなるオブジェクト(メインフォームでも良い)としてTFormListという
オブジェクトのメソッドに保存復帰を実装してみました.
 読み出すときには生成すべきクラスがストリームを読んでみないと決められない
のですが,ReadComponentResが動かないのでDelphiが元々持っているメカニズム
そのままでは使えません.そこでReaderを生成してクラス名をまず文字列として
読み出してからクラス参照を得,それを基にコンストラクタに多態させています.
 TForm の Create は exe の中のリソースを自動的に読み込んでしまうため,
裸の自分を生成するだけのコンストラクタである CreateNew を使って生成してい
ます.
CreateNew は Delphi 4.0 から virtual 化されて,大変使い易くなりました.


---------------------------------------------------------------------------
  TChartForm1 = class(TForm)       // 複数生成されて保存復帰の対象となるForm
  ......
  end;

  TChartForm2 = class(TChartForm1) // 同上
  ......
  end;
---------------------------------------------------------------------------
  TFormList = class(TComponent)  // 複数のFormをぶら下げるコンテナ(Owner)
  public
    procedure SaveForms;
    procedure RestoreForms;
  end;


procedure TFormList.RestoreForms;
var
  Fs: TMemoryStream;
  FName: string;
  Form: TForm;
  Reader: TReader;
  Pos: Integer;
  CompClass: string;
begin
  FName := 'FormSaveFile.fm1';
  if FileExists( FName ) then begin
    Fs := TMemoryStream.Create;
    try
      Fs.LoadFromFile( FName );
      Fs.Seek(0,0);
      while Fs.Position < Fs.Size do begin
        Pos := Fs.Position;
        // フォームのクラス名をストリームから読み出し,クラス参照を得る
        Reader := TReader.Create( Fs, 4096 );
        try
          Reader.ReadSignature;
          CompClass := Reader.ReadStr;
        finally
          Reader.Free;
        end;
        Form :=
            TFormClass( FindClass(CompClass) ).CreateNew( Self );
        Fs.Position := Pos;
        Fs.ReadComponent( Form );
        if Assigned(Form.OnCreate) then
          Form.OnCreate( Form );
      end;
    finally
      Fs.Free;
    end;
  end;
end;

procedure TFormList.SaveForms;
var
  Fs: TMemoryStream;
  i: integer;
  Form: TForm;
begin
  Fs := TMemoryStream.Create;
  try
    for i := 0 to ComponentCount-1 do begin
      Form := TForm( Components[i] );
      Fs.WriteComponent( Form );
    end;
    Fs.SaveToFile( 'FormSaveFile.fm1' );
  finally
    Fs.Free;
  end;
end;

中略

initialization
  RegisterClasses([ TChartForm1, TChartForm2 ]);  // Formのクラスを登録

                                                  TN(CQJ01721)
 


- FDELPHI  MES(16):玉石混淆みんなで作るSample蔵【見本蓄積】 00/07/09 -

Original document by TN            氏 ID:(CQJ01721)


ここにあるドキュメントは NIFTY SERVEの Delphi Users' Forum の16番会議室「玉石混淆みんなで作るSample蔵」に投稿されたサンプルです。これらのサンプルはボーランド株式会社がサポートする公式のものではありません。また、必ずしも動作が検証されているものではありません。これらのサンプルを使用したことに起因するいかなる損害も投稿者、およびフォーラムスタッフはその責めを負いません。使用者のリスクの範疇でご使用下さい。

Copyright 1996-2002 Delphi Users' Forum