TControlを変数で指定したい。


  2017-12-13 04:56:22  No: 48869

おばんさまです。

TControlを変数で指定したい。と思ったのですが、これは可能でしょうか?

con:=TControl(tedit).Create(form1);

のteditという部分を文字列でtbutton、tlistboxのように変数指定して使いたいのです。

var
s:string;
con:tcontrol;
begin
s:='tedit';
con:=TControl(s).Create(self);
end;


通りすがり  2017-12-13 05:35:54  No: 48870

http://docwiki.embarcadero.com/Libraries/Tokyo/ja/System.Classes.FindClass
はどうですか?


deldel  2017-12-13 22:31:16  No: 48871

ちょっと違うかもしれませんが、以下を応用できませんかね??

type
  TForm1 = class(TForm)
    Button1: TButton;
    Panel1: TPanel;
    Button2: TButton;
    Label1: TLabel;
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
    c: array [0..2] of TControl;

〜〜〜〜〜

procedure TForm1.FormCreate(Sender: TObject);
begin
  c[0] := Button1;
  c[1] := Panel1;
  c[2] := Label1;
end;

procedure TForm1.Button2Click(Sender: TObject);
const
  ib: Byte = 0;
begin
  inc(ib);
  c[ib mod 3].Left := c[ib mod 3].Left + 10;
end;


KONNOYA  2017-12-14 00:12:06  No: 48872

こんな方法ではどうですか?
環境が書かれていなかったのですが、とりあえず DelphiXE8 で試してみました。

【 FMXの場合 】

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Controls.Presentation,
  FMX.Edit, FMX.StdCtrls, FMX.Layouts, FMX.ListBox;

type
  TForm1 = class( TForm )
    procedure FormCreate     ( Sender : TObject );
    function  CreateMyControl( Parent : TObject; AName : String ) : TControl;
  private
    { private 宣言 }
    MyControl : TControl;
  public
    { public 宣言 }
  end;

  TTest = class( TControl );

var
  Form1: TForm1;

implementation

{$R *.fmx}

// フォーム生成処理
procedure TForm1.FormCreate( Sender : TObject );

begin
  // コントロール作成
  MyControl := CreateMyControl( Self, 'TLabel'   );
//  MyControl := CreateMyControl( Self, 'TEdit'    );
//  MyControl := CreateMyControl( Self, 'TButton'  );
//  MyControl := CreateMyControl( Self, 'TListBox' );

  // プロパティ設定
  // ※ もちろんプロパティはキャストするクラスにより変わります。
  TLabel( MyControl ).Width      := 100;
  TLabel( MyControl ).Height     := 100;
  TLabel( MyControl ).Position.X := 100;
  TLabel( MyControl ).Position.Y := 100;
  TLabel( MyControl ).Enabled    := TRUE;
  TLabel( MyControl ).Visible    := TRUE;
  TLabel( MyControl ).Text       := 'KONNOYA';
end;

// コントロール生成処理
function TForm1.CreateMyControl( Parent : TObject; AName : String ) : TControl;

var
  ClassFinder : TClassFinder;
  AClass      : TPersistentClass;
  AControl    : TControl;

begin
  // クラスファインダー生成
  ClassFinder := TClassFinder.Create;
  try
    // クラスを取得
    AClass         := ClassFinder.GetClass( AName );
    AControl       := AClass.NewInstance as TControl;
    AControl.Create( Self );
    AControl.Parent := Parent;
  finally
    // クラスファインダー解放
    ClassFinder.DisposeOf;
  end;

  // コントロールを返す
  Result := AControl;
end;

end.

【 VCLの場合 】

unit Unit1;

interface

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

type
  TForm1 = class( TForm )
    procedure FormCreate     ( Sender : TObject );
    function  CreateMyControl( Parent : TObject; AName : String ) : TControl;
  private
    { Private 宣言 }
    MyControl : TControl;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

// フォーム生成時処理
procedure TForm1.FormCreate( Sender : TObject );

begin
  // コントロール生成
  MyControl := CreateMyControl( Self, 'TLabel'   );
//  MyControl := CreateMyControl( Self, 'TEdit'    );
//  MyControl := CreateMyControl( Self, 'TButton'  );
//  MyControl := CreateMyControl( Self, 'TListBox' );

  // プロパティ設定
  // ※ もちろんプロパティはキャストするクラスにより変わります。
  TLabel( MyControl ).Width      := 100;
  TLabel( MyControl ).Height     := 100;
  TLabel( MyControl ).Left       := 100;
  TLabel( MyControl ).Top        := 100;
  TLabel( MyControl ).Enabled    := TRUE;
  TLabel( MyControl ).Visible    := TRUE;
  TLabel( MyControl ).Caption    := 'KONNOYA';
end;

// コントロール生成処理
function TForm1.CreateMyControl( Parent : TObject; AName : String ) : TControl;

type
  TPCDictionary = TDictionary< String, TPersistentClass >;

var
  ClassList   : TPCDictionary;

  ClassFinder : TClassFinder;
  AClass      : TPersistentClass;
  AControl    : TControl;

begin
  // ディクショナリ作成
  ClassList := TPCDictionary.Create;
  ClassList.Add( 'TLabel'  , TLabel   );
  ClassList.Add( 'TEdit'   , TEdit    );
  ClassList.Add( 'TButton' , TButton  );
  ClassList.Add( 'TListBox', TListBox );

  // クラスを取得
  ClassList.TryGetValue( AName, AClass );
  AControl        := AClass.NewInstance as TControl;
  AControl.Create( Self );
  AControl.Parent := Parent;

  // コントロールを返す
  Result := AControl;
end;

end.

VCLでは何故か TClassFinder が参照する FClassList.Items に
クラスのリストが格納されていない為、
自力でTDictionaryを作り、そこから探す様にしています。


tor  2017-12-14 01:43:48  No: 48873

「文字列」というところにこだわるのでなければ、
トではまたはクラス参照型というものを使って「型」そのものを変数に入れることができます。
(ただしいきなり変数宣言はできなくて、まずヲサヲサでその型を作っておく必要がありますが)

ヲサヲサ
ヲサヲサヲサヲサヤテヤヲサスヲサヲサヲサヤテサヲサッッヲサ「ヤテクラスの型を表す型」を作ってョョョ
ヲサヲサ
ヲサヲサヲサヲサコヲサヤテヤサヲサッッヲサその型の変数を宣言する
ヲサヲサヲサヲサコヲサヤナサ
ヲサヲサヲサヲサコヲサヤツサ
ヲサヲサ
ヲサヲサヲサヲサヲサコスヲサヤナサ
ヲサヲサヲサヲサヲサコスヲサョティモゥヲサヲサヤナサヲサッッヲサヤナができる
ヲサヲサヲサヲサョミヲサコスヲサモサ

ヲサヲサヲサヲサヲサコスヲサヤツサ
ヲサヲサヲサヲサヲサコスヲサョティモゥヲサヲサヤツサヲサッッヲサヤツができる
ヲサヲサヲサヲサョミヲサコスヲサモサ
ヲサヲササ

ヤテの型を受け取る関数というのも作ることができますね。

ヲサヲサ
ヲサヲサヲサヲサヤテヤヲサスヲサヲサヲサヤテサ

ヲサヲサヲサテティコヲサヤテヤサヲサコヲサヤテゥコヲサヤテサ
ヲサヲサ
ヲサヲサヲサヲサメヲサコスヲサョティゥサ
ヲサヲササ

ヲサヲサョョョ

ヲサヲサヲサコスヲサテティヤナャヲサモゥヲサヲサヤナサ
ヲサヲサヲサコスヲサテティヤツャヲサモゥヲサヲサヤツサ


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加