質問

実行時にコンポーネントを作成し、それを操作(プロパティの変更など)するにはどうすればよいですか

役に立ちましたか?

解決

視覚コンポーネントか非視覚コンポーネントかによって異なります。原則は同じですが、コンポーネントの種類ごとに追加の考慮事項があります。

非ビジュアルコンポーネントの場合

var
  C: TMyComponent;
begin
  C := TMyComponent.Create(nil);
  try
    C.MyProperty := MyValue;
    //...
  finally
    C.Free;
  end;
end;

ビジュアルコンポーネントの場合:

本質的に、視覚コンポーネントは、非視覚コンポーネントと同じ方法で作成されます。ただし、追加のプロパティを設定して表示する必要があります。

var
  C: TMyVisualComponent;
begin
  C := TMyVisualComponent.Create(Self);
  C.Left := 100;
  C.Top := 100;
  C.Width := 400;
  C.Height := 300;
  C.Visible := True;
  C.Parent := Self; //Any container: form, panel, ...

  C.MyProperty := MyValue,
  //...
end;

上記のコードのいくつかの説明:

  • コンポーネントの所有者(コンストラクターのパラメーター)を設定すると、所有するフォームが破棄されるとコンポーネントが破棄されます。
  • Parentプロパティを設定すると、コンポーネントが表示されます。忘れた場合、コンポーネントは表示されません。 (それを見逃すのは簡単です:))

多数のコンポーネントが必要な場合は、上記と同じことをループで実行できます。

var
  B: TButton;
  i: Integer;
begin
  for i := 0 to 9 do
  begin
    B := TButton.Create(Self);
    B.Caption := Format('Button %d', [i]);
    B.Parent := Self;
    B.Height := 23;
    B.Width := 100;
    B.Left := 10;
    B.Top := 10 + i * 25;
  end;
end;

これにより、フォームの左端に10個のボタンが追加されます。後でボタンを変更する場合は、リストに保存できます。 ( TComponentList は最適ではありませんが、コメントからこの回答への提案)

イベントハンドラを割り当てる方法:

イベントハンドラメソッドを作成し、イベントプロパティに割り当てる必要があります。

procedure TForm1.MyButtonClick(Sender: TObject);
var
  Button: TButton;
begin
  Button := Sender as TButton; 
  ShowMessage(Button.Caption + ' clicked');
end;

B := TButton.Create;
//...
B.OnClick := MyButtonClick;

他のヒント

ランタイムコンポーネントの作成プロセスを簡素化するには、 GExperts を使用できます。

  1. コンポーネント(または複数のコンポーネント)を視覚的に作成し、そのプロパティを設定します。
  2. 1つ以上のコンポーネントを選択し、GExperts、Components to Codeを実行します。
  3. 生成されたコードをアプリケーションに貼り付けます。
  4. ビジュアルフォームデザイナからコンポーネントを削除します。

例(この方法で生成されたTButton作成コード):

var
  btnTest: TButton;

btnTest := TButton.Create(Self);
with btnTest do
begin
  Name := 'btnTest';
  Parent := Self;
  Left := 272;
  Top := 120;
  Width := 161;
  Height := 41;
  Caption := 'Component creation test';
  Default := True;
  ParentFont := False;
  TabOrder := 0;
end;

コントロールを動的に追加するときに追加したいだけです... <!> lt; 1 <!> gt;で提案されているように、オブジェクトリスト(TObjectList)に追加することをお勧めします。 @Despatcherによって。

procedure Tform1.AnyButtonClick(Sender: TObject);
begin
  If Sender is TButton then
  begin
    Case Tbutton(Sender).Tag of 
    .
    .
    .
// Or You can use the index in the list or some other property 
// you have to decide what to do      
// Or similar :)
  end;
end;

procedure TForm1.BtnAddComponent(Sender: TObJect)
var
  AButton: TButton;
begin
  AButton := TButton.Create(self);
  Abutton. Parent := [Self], [Panel1] [AnOther Visual Control];
  AButton.OnClick := AnyButtonClick;
// Set Height and width and caption ect.
  .
  .
  . 
  AButton.Tag := MyList.Add(AButton);
end;

ユニット「Contnrs」を使用リストに追加する必要があります。 つまり、System.Contnrs.pasはベースコンテナユニットです そして、あなたは多くのオブジェクトリストを持つことができます。 使用するコントロールのタイプごとにTObjectListを使用することをお勧めします 例:

Interface
 Uses Contnrs;
Type
 TMyForm = class(TForm)
private
   { Private declarations }
public
   { Public declarations }
end;
 Var
  MyForm: TMyForm;
  checkBoxCntrlsList: TObjectList; //a list for the checkBoxes I will createin a TPanel
  comboboxCntrlsList: TObjectList; //a list of comboBoxes that I will create in some Form Container

これにより、どのタイプのコントロールかがわかるので、各コントロールを簡単に操作/管理できます。

Var comboBox: TComboBox;
I: Integer;

begin
 For I = 0 to comboboxCntrlsList.Count -1 do // or however you like to identify the control you are accessing such as using the tag property as @Despatcher said
   Begin
    comboBox := comboboxCntrlsList.Items[I] as TComboBox;
    ...... your code here
   End;
end;

これにより、そのコントロールのメソッドとプロパティを使用できます TObjectListsを、おそらくcreateイベントの形式で作成することを忘れないでください...

checkBoxCntrlsList := TObjectList.Create;
comboboxCntrlsList := TObjectList.Create;
  

ただし、作成するコンポーネントの数がわからない場合は、たとえばユーザーの決定に依存する場合。コンポーネントを動的に宣言するにはどうすればよいですか

答えが提案されています-最も簡単な方法は、オブジェクトのリスト(コンポーネント)です。 TObjectListは、最も簡単に使用できます(ユニット単位)。リストは素晴らしいです!

  In Form1 Public
  MyList: TObjectList;
  procedure AnyButtonClick(Sender: TObject); 

//より洗練された// TNotifyeventsを宣言してそれらを割り当てることができますが、単純にしておいてください:)   。   。   。

procedure Tform1.AnyButtonClick(Sender: TObject);
begin
  If Sender is TButton then
  begin
    Case Tbutton(Sender).Tag of 
    .
    .
    .
// Or You can use the index in the list or some other property 
// you have to decide what to do      
// Or similar :)
  end;
end;

procedure TForm1.BtnAddComponent(Sender: TObJect)
var
  AButton: TButton;
begin
  AButton := TButton.Create(self);
  Abutton. Parent := [Self], [Panel1] [AnOther Visual Control];
  AButton.OnClick := AnyButtonClick;
// Set Height and width and caption ect.
  .
  .
  . 
  AButton.Tag := MyList.Add(AButton);
end;

オブジェクトリストには任意のビジュアルオブジェクトを含めることができますが、どのアイテムがどのアイテムであるかを整理するオーバーヘッドが追加されます。たとえば、同様のパネルに複数の動的コントロールが必要な場合は、関連リストを用意することをお勧めします。

注:他のコメンターと同様に、簡潔にするために過度に簡略化したかもしれませんが、アイデアが得られれば幸いです。作成されたオブジェクトを管理するメカニズムが必要であり、リストはこのようなものに最適です。

<!> quot; xmlベースのテンプレートを使用したデルファイフォームの作成<!> quot;の調査中に、RTTIを指摘し、オープンツールapi(ToolsApi.pasと思います)を使用すると便利です。ユニットのインターフェースをご覧ください。

非常に簡単です。作成を呼び出します。例:

procedure test
var
  b : TButton;
begin
  b:=TButton.Create(nil);
  b.visible:=false;
end;

これにより、実行時にコンポーネント(TButtonはコンポーネント)が作成され、プロパティが表示されます。


コンストラクタの場合:メモリを自分で管理したい場合はnilを渡します。他のコンポーネントが破壊されたときに破壊したい場合は、別のコンポーネントにポインターを渡します。

一部のコンポーネントは「Loaded」メソッドをオーバーライドします。実行時にインスタンスを作成する場合、このメソッドは自動的に呼び出されません。フォームファイル(DFM)からの読み込みが完了すると、Delphiによって呼び出されます。

メソッドに初期化コードが含まれている場合、アプリケーションは実行時に作成されるときに予期しない動作を示す場合があります。この場合、コンポーネントの作成者がこのメソッドを使用しているかどうかを確認してください。

グループボックス/ページコントロール/などでwinコントロールをネストする場合、親グループボックスを所有者にすることは有益だと思います。所有者が常にメインフォームであるのとは対照的に、これを行うとウィンドウを閉じる時間が大幅に減少することに気付きました。

これは、Evernoteでボタンタグをエミュレートする方法の例です

unit Unit7;

interface

uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, CHButton, Vcl.ExtCtrls, RzPanel, CHPanel, RzCommon,RzBmpBtn, Vcl.StdCtrls;

type
  // This is panel Button
  TButtonClose = class (TRzPanel)
   CloseButton : TRzBmpButton;
   procedure CloseButtonClick(Sender: TObject);
   procedure CloseButtonMouseEnter(Sender: TObject);
   procedure MouseDown(Sender: TObject; Button: TMouseButton;
             Shift: TShiftState; X, Y: Integer);
   procedure MouseUp(Sender: TObject; Button: TMouseButton;
             Shift: TShiftState; X, Y: Integer);
public
   constructor Create(AOwner: TComponent); override;
   destructor Destroy; override;
end;

TForm7 = class(TForm)
   CHButton1: TCHButton;
   RzPanel1: TRzPanel;
   RzBmpButton1: TRzBmpButton;
   procedure CHButton1Click(Sender: TObject);
   procedure RzBmpButton1Click(Sender: TObject);
   procedure RzPanel1MouseDown(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
   procedure RzPanel1MouseUp(Sender: TObject; Button: TMouseButton;
     Shift: TShiftState; X, Y: Integer);
   procedure RzPanel1MouseEnter(Sender: TObject);
   procedure RzBmpButton1MouseEnter(Sender: TObject);
   procedure FormMouseEnter(Sender: TObject);
   procedure FormCreate(Sender: TObject);
private
  { Private declarations }
public
  { Public declarations }
end;

var
  Form7: TForm7;
  MyCloseButton : TButtonClose;

implementation

{$R *.dfm}

// constructor for on the fly component created
constructor TButtonClose.Create(AOwner: TComponent);
begin
   inherited Create(AOwner);

   // Set Events for the component
   Self.OnMouseEnter := Self.CloseButtonMouseEnter;
   Self.OnMouseDown := Self.MouseDown;
   Self.OnMouseUp := Self.MouseUp;
   Self.Height := 25;

   // Close button on top panel Button
   // Inherited from Raize Bitmap Button
   CloseButton := TRzBmpButton.Create(self);
   // Set On Click Event for Close Button
   CloseButton.OnClick := Self.CloseButtonClick;
   // Place Close Button on Panel Button
   CloseButton.Parent := self;
   CloseButton.Left := 10;
   CloseButton.Top := 5;
   CloseButton.Visible := False;
   // Setting the image for the button
   CloseButton.Bitmaps.Up.LoadFromFile(ExtractFilePath(Application.ExeName)+'\close.bmp');
end;

procedure TButtonClose.CloseButtonClick(Sender: TObject);
begin
   // Free the parent (Panel Button)
   TControl(Sender).Parent.Free;
end;

procedure TButtonClose.CloseButtonMouseEnter(Sender: TObject);
begin
   // Show the Close button
   CloseButton.Visible := True;
end;

procedure TButtonClose.MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
   // Emulate Button down state, since it is panel
   TRzPanel(Sender).BorderOuter := fsLowered;
end;

procedure TButtonClose.MouseUp(Sender: TObject; Button: TMouseButton;
 Shift: TShiftState; X, Y: Integer);
begin
   // Emulate Button up state, since it is panel
   TRzPanel(Sender).BorderOuter := fsRaised;
end;

destructor TButtonClose.Destroy;
begin
   inherited Destroy;
end;

procedure TForm7.FormCreate(Sender: TObject);
begin
   // Create Panel Button on the fly
   MyCloseButton := TButtonClose.Create(self);
   MyCloseButton.Caption := 'My Button';
   MyCloseButton.Left := 10;
   MyCloseButton.Top := 10;
   // Don't forget to place component on the form
   MyCloseButton.Parent := self;
end;

procedure TForm7.FormMouseEnter(Sender: TObject);
begin
   if Assigned(RzBmpButton1) then
      RzBmpButton1.Visible := False;

   // Hide when mouse leave the button
   // Check first if myCloseButton Assigned or not before set visible property
   if Assigned(MyCloseButton.CloseButton) then
      MyCloseButton.CloseButton.Visible := False;
end;

procedure TForm7.RzBmpButton1Click(Sender: TObject);
begin
   TControl(Sender).Parent.Free;
end;

procedure TForm7.RzBmpButton1MouseEnter(Sender: TObject);
begin
   RzBmpButton1.Visible := True;
end;

procedure TForm7.RzPanel1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  TRzPanel(Sender).BorderOuter := fsLowered;
end;

procedure TForm7.RzPanel1MouseEnter(Sender: TObject);
begin
   RzBmpButton1.Visible := True;
end;

procedure TForm7.RzPanel1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
   TRzPanel(Sender).BorderOuter := fsRaised;
end;

procedure TForm7.CHButton1Click(Sender: TObject);
begin
   FreeAndNil(Sender);
end;

end.
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top