喫茶XRAYトップページ

[スレッド全体
]

[11113] Re6:コンポーネントの保存返信 削除
2017/4/17 (月) 15:05:47 taki
> それと、AAA.binの内容はバイナリーの情報である事を付け加えておきます。
> つまり、.dfmファイルとは異なります。


ReadComponentメソッドを検索していたら、こんなページに出くわしました。
http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Classes_TStream_ReadComponent.html

その中の Delphi Examples に超超ステキな手続きがありました。

コードを実行してみたら、.dfmファイルに出力される物と同じ?と思われる
文字列がMemoに得られました。

それを参考にして以下のようなコードを作成して試しました。

Button3でStringGridを動的に生成します。
ExamplesではFormCreateで行われる内容です。

Button1でそれをテキスト化します。Memoに文字列が表示されます。
MemoはScrollBarsをssBothにしておいてください。

Button2でStringGridをFreeした後、Memoのテキストから
コンポーネントを生成します。

----------------------------------
unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    Button3: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  published
    procedure MyEvent(Sender: TObject);
  end;

var
  Form1: TForm1;
  StringGrid1 : TStringGrid;
  LMethod : TMethod;

implementation

{$R *.dfm}

function ComponentToStringProc(Component: TComponent): string;
var
  BinStream:TMemoryStream;
  StrStream: TStringStream;
  s: string;
begin
  BinStream := TMemoryStream.Create;
  try
    StrStream := TStringStream.Create(s);
    try
      BinStream.WriteComponent(Component);
      BinStream.Seek(0, soFromBeginning);
      ObjectBinaryToText(BinStream, StrStream);
      StrStream.Seek(0, soFromBeginning);
      Result:= StrStream.DataString;
    finally
      StrStream.Free;
    end;
  finally
    BinStream.Free
  end;
end;

function StringToComponentProc(Value: string): TComponent;
var
  StrStream:TStringStream;
  BinStream: TMemoryStream;
begin
  StrStream := TStringStream.Create(Value);
  try
    BinStream := TMemoryStream.Create;
    try
      ObjectTextToBinary(StrStream, BinStream);
      BinStream.Seek(0, soFromBeginning);
      Result:= BinStream.ReadComponent(nil);
    finally
      BinStream.Free;
    end;
  finally
    StrStream.Free;
  end;
end;

// コンポーネントを文字列化
procedure TForm1.Button1Click(Sender: TObject);
begin
  if Assigned(StringGrid1) then Memo1.Text := ComponentToStringProc(StringGrid1);
end;

// 文字列からコンポーネント生成
procedure TForm1.Button2Click(Sender: TObject);
begin
  if Length(Memo1.Text) <= 10 then exit;
  if Assigned(StringGrid1) then StringGrid1.Free;
  StringGrid1 := (StringToComponentProc(Memo1.Text) as TStringGrid);
  StringGrid1.Parent := Form1;
  StringGrid1.Visible := true;
  StringGrid1.Repaint;

  sleep(1000);
  StringGrid1.Top := 200;

  //------ やはりここでイベントを登録しないとダメみたい
{
  LMethod.Data := Self;
  LMethod.Code := Self.MethodAddress('MyEvent');
  if Assigned(LMethod.Code) then begin
    StringGrid1.OnClick := TNotifyEvent(LMethod);
  end;
}
  //--------------------------------------
end;

// テスト対象のStringGridを動的に生成
procedure TForm1.Button3Click(Sender: TObject);
begin
  if Assigned(StringGrid1) then begin
    showmessage('既に存在しています。');
    exit;
  end;
  StringGrid1 := TStringGrid.Create(Form1);
  StringGrid1.Parent := Form1;
  StringGrid1.Name := 'Ojisan';   // 名前は英数のみ有効
  StringGrid1.Top := 70;
  StringGrid1.Left := 330;
  StringGrid1.Options := StringGrid1.Options + [goRowSizing,goColSizing,goEditing];
  StringGrid1.Cells[2,2] := 'データ';
  StringGrid1.ColWidths[2] := 100;
//------- イベントの登録
  LMethod.Data := Self;
  LMethod.Code := Self.MethodAddress('MyEvent');
  if Assigned(LMethod.Code) then begin
    StringGrid1.OnClick := TNotifyEvent(LMethod);
  end;
end;

// 実行されるイベント
procedure TForm1.MyEvent(Sender: TObject);
begin
  ShowMessage('Clicked !!');
end;


initialization

  RegisterClass(TStringGrid);
// 文字入力を行うとInplaceEditを使うのでここに登録する
// 登録しないと 'クラスTInplaceEditが見つかりません'のエラーが出る
  RegisterClass(TInplaceEdit);

end.

----------------------------------

結果は形状(セルの幅とか高さ)、OptionsなどはText化されますが、
セル内のデータとイベントは保存されないようです。

でも.dfmファイルには[OnClick = Button1Click]のようなイベントに
関連した文字列があるので、どこかにあるんでしょうね。


[11115] Re7:コンポーネントの保存返信 削除
2017/4/17 (月) 15:29:18 Mr.XRAY
▼ takiさん

> ReadComponentメソッドを検索していたら、こんなページに出くわしました。
> http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/Classes_TStream_ReadComponent.html


おおっ !!
そうか, ObjectBinaryToText なんてのを忘れていました.
ハハハッ.
しかし,taki さんってぱ.
精通していないからと言って逃げない人なんですね.( <-- しつこい ! )
いや〜,いえ,いやじゃないけど.このスレッド役に立ちますね.


[11116] Re8:コンポーネントの保存返信 削除
2017/4/17 (月) 15:42:16 Mr.XRAY
> そうか, ObjectBinaryToText なんてのを忘れていました.

サイト内で一か所だけですが,使っていました.
保存はバイナリですが.

[130] [03_TMemoryStream を使用したコンポーネントの保存と読み出し]
http://mrxray.on.coocan.jp/Delphi/plSamples/130_SaveComponent.htm#03


[11117] Re7:コンポーネントの保存返信 削除
2017/4/17 (月) 18:18:32 Mr.XRAY
▼ takiさん

> 結果は形状(セルの幅とか高さ)、OptionsなどはText化されますが、
> セル内のデータとイベントは保存されないようです。


ですね.保存されるのは published なプロパティだけですから.

というわけで,またまた人様のフンドシでなのですが,
記事を追加されていただきました.スミマセンね.
でも,きっと他の方にも役に立つと思いますのでご容赦願います.

[130] [04_コンポーネントをテキスト形式で保存]
http://mrxray.on.coocan.jp/Delphi/plSamples/130_SaveComponent.htm#04


[▼次のスレッド]
INCM/CMT
Cyclamen v3.82