Accéder aux objets dynamique [Résolu]

Signaler
Messages postés
118
Date d'inscription
samedi 9 décembre 2006
Statut
Membre
Dernière intervention
17 novembre 2009
-
Messages postés
814
Date d'inscription
vendredi 3 novembre 2000
Statut
Membre
Dernière intervention
30 juillet 2009
-
Salut à tous,
Je crée dynamiquement un ComboBox sur une Form.
J'ai élaguer volontairement le code pour ne pas surchager....

var
  CmBx: TComboBox;
  Objects: array of TControl;
..............
CmBx := TComboBox.Create(Self);
with CmBx do
  begin
    Parent := Self;
    Name := 'CB1';
    OnClick := CmBxClick;
    SetBounds(100, 100, 150, 17);
  end;
SetLength(Objects, Length(Objects) + 1);
Objects[High(Objects)] := CmBx;

On peut charger la ComboBox par : CmBx.Items.Add(NomVariable);
On peut lire sur Click avec : variable := CmBx.Text;

Ca c'est bien quand on a 1 ComboBox... Mais avec plusieurs CB1, CB2 ?????

A+
Merci

10 réponses

Messages postés
4200
Date d'inscription
samedi 16 octobre 2004
Statut
Modérateur
Dernière intervention
13 juin 2020
30
procedure TForm1.FormCreate(Sender: TObject);
var N,II,OT,OH : integer;
begin
  CreateChild('',TEdit,Self,10,10,II);
  with DynamicCtrls.Items[II] as TEdit do
  begin
    Text := 'Hahahahaha';
    OT := Top;
    OH := Height;
  end;

  CreateChild('',TComboBox,Self,10,OT+OH+8,II);
  with DynamicCtrls.Items[II] as TComboBox do
  begin
    for N := 1 to 10 do
        Items.Add(IntToStr(N));
  end;
end;



function TForm1.CreateChild(const AName : string; AClass : TControlClass;
                            AParent : TWinControl; const ALeft, ATop : integer;
                            var VIndex : integer) : TControl;

begin
  result := AClass.Create(nil);
  VIndex := fDynCtrlList.Add(result);





DynamicCtrls fonctione comme la propriété Items ou Lines d'une ListBox ou Memo, juste que la ce n'est pas des chaines mais des objets.

pour assigner les evenements, tu créer des gestionnaire dans l'objet ou la fiche que tu desire, puis, tu assigne les gestionnaires comme suis :

CreateChild('DEdit1',TEdit,Self,10,10,II);
with DynamicCtrls.Items[II] as TEdit do
begin
  Text       := '';
  OnClick    := DoDEdit1Click;
  OnChange   := DoDEdit1Change;
  OnKeyPress := DoDEdit1KeyPress;
end;

<hr size="2" width="100%" />Croc (click me)
Messages postés
4200
Date d'inscription
samedi 16 octobre 2004
Statut
Modérateur
Dernière intervention
13 juin 2020
30
ah et pour enlever un objet de la fiche tu fait :

DynamicCtrls.Delete(index de l'objet);

Delete s'occupera de la suppression et liberation de l'objet.

<hr size="2" width="100%" />Croc (click me)
Messages postés
814
Date d'inscription
vendredi 3 novembre 2000
Statut
Membre
Dernière intervention
30 juillet 2009
3
salut,

var
MesCB : array[1..NBCB] of TcomboBox;

for i := 1 to NBCB do begin
CmBx := TComboBox.Create(Self);
with CmBx do
  begin
    Parent := Self;
//    Name := 'CB1'; // inutile ou CB + inttostr(i)
    OnClick := CmBxClick;
    SetBounds(100, 100+i*..., 150, 17);
   tag := i; // si ça t'aide....
  end;
  MesCB[i]:=cmbx;
end;
n'oublie pas que les event pass en param le "sender" ! Aussi, rappel toi le champs tag!

A+

Loda
<hr size="2" width="100%" />Se poser les bonnes questions est le premier pas pour trouver les bonnes réponses.
Messages postés
118
Date d'inscription
samedi 9 décembre 2006
Statut
Membre
Dernière intervention
17 novembre 2009

Re,
J'ai pris un tableau TControl car mets dedans aussi du TCheckBox et du TEdit.
Ca ne change pas grand chose. J'avais déjà vu la possibilité d'utiliser Tag, qui peut-être fort util dans ce cas. Mais pour accéder aux propriétés du compo, il existe peut-être un manière plus simple que :
for i:=0 to Length(Objects)-1 do
  begin
    if Objects[i].Tag = 2
    ou
    if Objects[i].Name = 'CB1'
  end;
pour récupérer l'indice de l'objet.....
A+
Messages postés
118
Date d'inscription
samedi 9 décembre 2006
Statut
Membre
Dernière intervention
17 novembre 2009

Salut Loda,
J'étais en train de relire ton message, et je pense que tu as la solution. Je m'acharne à avoir un tableau TControl pour pouvoir mettre toute sorte de composants, alors que déclarer un tableau par composant TComboBox, TCheckBox, TEdit est plus lourd en code, mais plus simple à gérer (remplir des listes, extraire des données...)
Qu'en penses-tu ?
A+.
Messages postés
4200
Date d'inscription
samedi 16 octobre 2004
Statut
Modérateur
Dernière intervention
13 juin 2020
30
ptite technique de derriere les fagots :

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Contnrs;

type
  TControlClass = class of TControl;

  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    fDynCtrlList  : TObjectList;
  protected
  public
   constructor Create(AOwner : TComponent); override;
   destructor Destroy; override;
   function CreateChild(const AName : string; AClass : TControlClass;
                        AParent : TWinControl; const ALeft, ATop : integer;
                        var VIndex : integer) : TControl;
   property DynamicCtrls : TObjectList read fDynCtrlList write fDynCtrlList;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TForm1.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  fDynCtrlList := TObjectList.Create(true);
end;

function TForm1.CreateChild(const AName : string; AClass : TControlClass;
                            AParent : TWinControl; const ALeft, ATop : integer;
                            var VIndex : integer) : TControl;
begin
  result := AClass.Create(nil);
  VIndex := fDynCtrlList.Add(result);
  with Result do
  begin
    if Length(AName) >= 2 then
       Name   := AName
    else
       Name   := 'DynamicCtrl'+IntToStr(fDynCtrlList.Count);

    if AParent <> nil then
       Parent := AParent;

    SetBounds(ALeft,ATop,Width,Height);
  end;
end;

destructor TForm1.Destroy;
begin
  fDynCtrlList.Clear;
  fDynCtrlList.Free;
  inherited Destroy;
end;

procedure TForm1.FormCreate(Sender: TObject);
var N,II,OT,OH : integer;
begin
  CreateChild('',TEdit,Self,10,10,II);
  with DynamicCtrls.Items[II]as TEdit do
  begin
    Text := 'Hahahahaha';
    OT := Top;
    OH := Height;
  end;

  CreateChild('',TComboBox,Self,10,OT+OH+8,II);
  with DynamicCtrls.Items[II] as TComboBox do
  begin
    for N := 1 to 10 do
        Items.Add(IntToStr(N));
  end;
end;

<hr size="2" width="100%" />Croc (click me)
Messages postés
118
Date d'inscription
samedi 9 décembre 2006
Statut
Membre
Dernière intervention
17 novembre 2009

Salut,
En ce moment je me connecte en pointillés j'ai des problèmes sur la ligne.
La, FOxi nous présente THE code....
J'aime bien, c'est clair et nul doute efficace...
Petite question, ta variable II (Vindex) est initialisée comment ?Dans mon cas, je veux faire apparaître les compos "à la volée" (un click sur une cellule d'un STringGrid visible  une autre cellule libéré). Je pense qu'il suffit de déclaré CreateChild non pas dans FormCreate mais dans OnSelectCell.
Par contre pour récupérer les données de ces compos comment utiliser DynamicCtrls ?
(Par exemple le OnClick d'un ComboBox remplis la cellule 1,1 d'un TStringGrid)
A+
et merci de vos efforts
Messages postés
118
Date d'inscription
samedi 9 décembre 2006
Statut
Membre
Dernière intervention
17 novembre 2009

Ok, c'est clair, en plus j'aime bien ce code.
Il ne me reste qu'a me mettre au clavier....
Merci
A+
Messages postés
118
Date d'inscription
samedi 9 décembre 2006
Statut
Membre
Dernière intervention
17 novembre 2009

Grand merci
A+
Messages postés
814
Date d'inscription
vendredi 3 novembre 2000
Statut
Membre
Dernière intervention
30 juillet 2009
3
salut,

"Mais pour accéder aux propriétés du compo"

1. une recherche (ie: for) dans le tableau selon un critère (tag, name, type, ...)
2. tu garde le pointeur quelque part. (ex: dans le champs object d'une stringlist) -> acces (presque) sans recherche. Attention au AV.
3.tu ne garde pas le compo dans un tableau mais dans une var réservée pour cette usage. (var EdtDynClientName, ....)

bon code,

Loda
<hr size="2" width="100%" />Se poser les bonnes questions est le premier pas pour trouver les bonnes réponses.