喫茶XRAYトップページ

[スレッド全体
]

[11062] procedure手続きを手続き名で検索できますか返信 削除
2017/4/10 (月) 19:06:04 taki
動的にコンポーネントを生成しているのですが、text等に記録した文字列から生成したいのです。
TopとかLeftとかCaptionとかは文字列から値を代入できます。
MyButton.ParentはGetComponentByName()という関数を作って文字列'Panel1'からTWinControlを
得ることができたのですが、MyEvent手続きを手続き名'MyEvent'から探す方法が分かりません。

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.ExtCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Panel1: TPanel;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
    MyButton:TButton;
    procedure MyEvent(Sender: TObject);
    function GetComponentByName(AName:String):TComponent;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function TForm1.GetComponentByName(AName:String):TComponent;
var
  i:integer;
begin
  result := self;     // 無かったらForm1に生成
  if Form1.ComponentCount = 0 then exit;
  for i := 0 to Form1.ComponentCount - 1 do begin
    if Form1.Components[i].Name = AName then begin
      result := Form1.Components[i];
      exit;
    end;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  MyButton := TButton.Create(Self);
  MyButton.Parent := GetComponentByName('Panel1') as TWinControl;
//Panel1上にボタンを生成している
  MyButton.Top := 20;
  MyButton.Left := 20;
  MyButton.Caption := '私のボタン';
  MyButton.OnClick := MyEvent;  // ← ここの値を'MyEvent'から得たい
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if MyButton <> nil then FreeAndNil(MyButton);
end;

procedure TForm1.MyEvent(Sender: TObject);
begin
  beep;
end;

end.


[11086] TWinControlを検索返信 削除
2017/4/11 (火) 19:51:16 Mr.XRAY
>   MyButton.OnClick := MyEvent;  // ← ここの値を'MyEvent'から得たい

ができるようになったところで,

  MyButton.Parent := GetComponentByName('Panel1') as TWinControl;

なんですが,以下のようにできる気がします.
親コントロール(コンテナ)になれるのは TWindControl だけですから,
FindControl は TWinControl だけを検索します.

  MyButton.Parent := FindControl(Panel2.Handle);

http://docwiki.embarcadero.com/Libraries/Berlin/ja/Vcl.Controls.FindControl

[追記]
つまり,こういう感じです.

type
  TForm1 = class(TForm)
    Button1: TButton;
    Panel1: TPanel;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
    MyButton : TButton;
  public
    { Public 宣言 }
  published
    procedure MyEvent(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  LMethod : TMethod;
begin
  MyButton := TButton.Create(Self);
  MyButton.Parent := FindControl(Panel1.Handle);
  MyButton.Top := 20;
  MyButton.Left := 20;
  MyButton.Caption := '私のボタン';

  LMethod.Data := Self;
  LMethod.Code := Self.MethodAddress('MyEvent');
  if Assigned(LMethod.Code) then begin
    MyButton.OnClick := TNotifyEvent(LMethod);
  end;
end;

procedure TForm1.MyEvent(Sender: TObject);
begin
  ShowMessage('Clicked !!');
end;



[11092] publishedに記述する意味返信 削除
2017/4/13 (木) 17:18:22 taki
▼ Mr.XRAYさん
 
> [追記]
> つまり,こういう感じです.
>
> type
>   TForm1 = class(TForm)
>     Button1: TButton;
>     Panel1: TPanel;
>     procedure Button1Click(Sender: TObject);
>   private
>     { Private 宣言 }
>     MyButton : TButton;
>   public
>     { Public 宣言 }
>   published
>     procedure MyEvent(Sender: TObject);
>   end;


http://mrxray.on.coocan.jp/Delphi/plSamples/122_PluralForms.htm
「09_他のフォームのユニットの変数やメソッド類を使う」の最後の方に

type
  TMyClass = class(TObject)
    //ここには書かないこと(Delphiが使用する特別な領域)
  private
    //ここに書いた変数やメソッド,関数類は同じユニット内だけでアクセス可能
    //他のユニットからはアクセスできない
  protected
    //ここに書いた変数やメソッド,関数類は同じユニット内だけでアクセス可能
    //他のユニットからはアクセスできない
  public
    //ここに書いた変数やメソッド,関数類はどのユニットからもアクセス可能
  published
    //ここに書いた変数やメソッド,関数類はどのユニットからもアクセス可能
  end;

というのがありました。
なので、マスターのコードではpubulicの下にpublishedを追加してそこにMyEventを
記述してあるのですね。

「11_public 部と published 部の違い」の説明中に
「また,published 部のメンバーは,クラスのインスタンス (TButton ならば Button1 等) を
ファイルに保存すると,その設定値もファイルに保存されます.public 部の値は保存されません.」
とあるのですが、ファイルに保存の意味が分かりません。
TButton.SaveToFile()みたいなのがあるのかと思いましたが無いし。


[11093] コンポーネントの保存返信 削除
2017/4/13 (木) 18:35:46 Mr.XRAY
▼ takiさん

> 「11_public 部と published 部の違い」の説明中に

これなんですが,まず,TForm は特別でして,published に書いても
オブジェクトインスペクタには表示されません.で,

> ファイルに保存すると,その設定値もファイルに保存されます.public 部の値は保存されません.」

これなんですが,コンポーネントの保存は,ストリームとして保存します.
上のサンプルの Button1 クリックを以下のように変更し,
TButton を 1 つ追加して,この Button2 のクリックイベントを以下のようにします.

procedure TForm1.Button1Click(Sender: TObject);
var
  LMethod : TMethod;
  LFileStream : TFileStream;
begin
  MyButton := TButton.Create(Self);
  MyButton.Parent := FindControl(Panel1.Handle);
  MyButton.Top := 20;
  MyButton.Left := 20;
  MyButton.Caption := '私のボタン';

  LMethod.Data := Self;
  LMethod.Code := Self.MethodAddress('MyEvent');
  if Assigned(LMethod.Code) then begin
    MyButton.OnClick := TNotifyEvent(LMethod);
  end;

  //コンポーネントの保存
  LFileStream := TFileStream.Create('AAA.bin', fmCreate);
  try
    LFileStream.WriteComponent(MyButton);
  finally
    FreeAndNil(LFileStream);
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  LFileStream : TFileStream;
  LMyButton : TButton;
begin
  //同名のコンポーネントは作成できないので別の名前にする
  //Button1クリックの直後に実行することも考慮
  LMyButton := TButton.Create(Self);

  //コンポーネントの読み込み
  //イベント用のメソッドはTForm1のメンバなので保存はされていない
  //イベントを保存するには,TButtonの継承クラスを作成して,そのイベントを作成する
  LFileStream := TFileStream.Create('AAA.bin', fmOpenRead);
  try
    LFileStream.ReadComponent(LMyButton);
    //親(コンテナ)を設定しないと表示できないでエラー
    LMyButton.Parent := Panel1;
    LMyButton.Update;

    Sleep(1000);
    LMyButton.Top := 100;
  finally
    FreeAndNil(LFileStream);
  end;
end;

そして,以下の手順でコンポーネントが保存されたことを確認できます.

(1) EXE を起動して Button1 をクリック
    AAA.bin というファイルができる
(2) EXE を閉じる
(3) 再度 EXE を起動して Button2 をクリック

動作確認は Windows 7 U64(SP1) + Delphi XE(UP1) Pro でござんす.


下の図は Buttpm2 をクリックして 1 秒後の状態

[11118] Re:コンポーネントの保存返信 削除
2017/4/19 (水) 09:05:35 おかぽん
▼ Mr.XRAYさん

Published でないプロパティの保存と読み込み
http://docwiki.embarcadero.com/RADStudio/Tokyo/ja/Published_%E3%81%A7%E3%81%AA%E3%81%84%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3%E3%81%AE%E4%BF%9D%E5%AD%98%E3%81%A8%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%81%BF

やりたいことは、こういうことでは・・・ない・・・?


MemoryStream.WriteComponentで、書き出しされているところまでは確認しました。

type
  TStringGrid=class(Grids.TStringGrid)
  protected
    procedure DefineProperties(Filer: TFiler); override;
    procedure ReadValues(Reader : TReader);
    procedure WriteValues(Writer : TWriter);
  end;

procedure TStringGrid.DefineProperties(Filer: TFiler);
begin
  inherited DefineProperties(Filer);
  Filer.DefineProperty('CellString', ReadValues, WriteValues, True);
end;
procedure TStringGrid.ReadValues(Reader : TReader);
begin
  Reader.ReadListBegin;
  Cells[1,1] := Reader.ReadString;
  Cells[1,2] := Reader.ReadString;
  Reader.ReadListEnd;
end;
procedure TStringGrid.WriteValues(Writer : TWriter);
begin
  Writer.WriteListBegin;
  Writer.WriteString(Cells[1,1]);
  Writer.WriteString(Cells[1,2]);
  Writer.WriteListEnd;
end;



[11119] Re2:コンポーネントの保存返信 削除
2017/4/19 (水) 10:34:37 Mr.XRAY
▼ おかぽんさん.どうもです.

> Published でないプロパティの保存と読み込み
> http://docwiki.embarcadero.com/RADStudio/Tokyo/ja/Published_%E3%81%A7%E3%81%AA%E3%81%84%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3%E3%81%AE%E4%BF%9D%E5%AD%98%E3%81%A8%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%81%BF
>
> やりたいことは、こういうことでは・・・ない・・・?


おおっ,TWriter, TReader ですね.
↓ には
『published 以外のプロパティの保存には,特別な方法が必要です
(拙作のコンポーネントでは使用しています).』
としか書いてないんです.

[130] [01_オブジェクトの保存と読み出し]
http://mrxray.on.coocan.jp/Delphi/plSamples/130_SaveComponent.htm#01

Halbow 資料館には TWriter, TReader 使ったコードがあるんですが,
折角サンプルコードを頂いたので,これも掲載しちゃおうかな.
タイトルは「published 以外のプロパティの保存方法」とか...


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