Autor Beitrag
BigBossMan
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 32



BeitragVerfasst: Mi 18.08.04 12:35 
Hallo Leute !

Wie kann ich eine dyn. Form beliebig oft mit einen Buttonclick öffnen ?

Hier mein Code:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
var
 cForm: array of TForm;

procedure TFormMain.FileForm1Execute(Sender: TObject);
var
 n: Integer;
begin
 n := 0;
 while n >= 0 do
 if not cForm[n].Visible then
 begin
  cForm[n].Top := 100;
  cForm[n].Caption := 'NeueForm'+IntToStr(n);
  cForm[n].Name := 'NeueForm'+IntToStr(n);
  cForm[n].Show;
  n := -1;
 end;
end;


Aber das geht bei mir nicht, kommt einr Fehlermeldung. "EAccess Volation"

Vielen Dank im voraus.

Mfg

Moderiert von user profile iconMotzi: Code- durch Delphi-Tags ersetzt.
Inferno
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 76



BeitragVerfasst: Mi 18.08.04 12:50 
Hi,

hm also 2 dinge vorweg, in deinem Code fehlt ausjedenfall das erzeugen der Form

ausblenden Delphi-Quelltext
1:
  cForm[n] := TForm.Create;					


und wenn du ein dynamisches Array hast musst du mit SetLenght() erstmal die größe des Arrays setzten bevor du damit was machen kannst.

Also ich würde dir empfehlen das ganze mit Zeigern und ner TList zu Lösen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
type
  pForm = ^TForm;
  

var
  aForm : pForm;
  n     : integer;
  Liste : TList;

procedure TFormMain.FileForm1Execute(Sender: TObject);
begin
  GetMem(aForm, SizeOf(TForm));
  aForm^ := TForm.Create;
  with aForm^ do
  begin
    inc(n);
    Caption := 'Form ' + IntToStr(n)
    {...} // andere eigentschaften setzen
  end;
  Liste.Add(aForm);
end;


Wichtig irgendwo die Liste zu erstellen mit:

ausblenden Delphi-Quelltext
1:
  Liste := TList.Create;					


und auch wieder freigeben am ende.


ausblenden Delphi-Quelltext
1:
  Liste.Free;					


So nun haste alle neu erstellen Formen als Pointer in der Liste. Schau am besten dann mal zu TList in die hilfe, is aber einfach zu handeln.

Ok hoffe hab hier keinen murks geschrieben, wenn doch bitte berichtigt mich ;)


mfg
Inferno
BigBossMan Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 32



BeitragVerfasst: Mi 18.08.04 13:43 
Inferno hat folgendes geschrieben:
Hi,

hm also 2 dinge vorweg, in deinem Code fehlt ausjedenfall das erzeugen der Form

ausblenden Delphi-Quelltext
1:
  cForm[n] := TForm.Create;					


und wenn du ein dynamisches Array hast musst du mit SetLenght() erstmal die größe des Arrays setzten bevor du damit was machen kannst.

Also ich würde dir empfehlen das ganze mit Zeigern und ner TList zu Lösen:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
type
  pForm = ^TForm;
  

var
  aForm : pForm;
  n     : integer;
  Liste : TList;

procedure TFormMain.FileForm1Execute(Sender: TObject);
begin
  GetMem(aForm, SizeOf(TForm));
  aForm^ := TForm.Create;
  with aForm^ do
  begin
    inc(n);
    Caption := 'Form ' + IntToStr(n)
    {...} // andere eigentschaften setzen
  end;
  Liste.Add(aForm);
end;


Wichtig irgendwo die Liste zu erstellen mit:

ausblenden Delphi-Quelltext
1:
  Liste := TList.Create;					


und auch wieder freigeben am ende.


ausblenden Delphi-Quelltext
1:
  Liste.Free;					


So nun haste alle neu erstellen Formen als Pointer in der Liste. Schau am besten dann mal zu TList in die hilfe, is aber einfach zu handeln.

Ok hoffe hab hier keinen murks geschrieben, wenn doch bitte berichtigt mich ;)


mfg
Inferno


Ok es geht, aber wenn ich die Eigenschaft Namen mit eingebe kommt eine Fehlermeldung das die Form schon existiert.
Wie kann man das Problem lösen ?

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
procedure TFormMain.FileForm1Execute(Sender: TObject);
var
 aForm : pForm;
 n     : integer;
begin
 n := 0;
 FListe := TList.Create;
 GetMem(aForm, SizeOf(TForm));
 aForm^ := TForm.CreateNew(Application);
 with aForm^ do
 begin
  inc(n);
  Caption := 'Form ' + IntToStr(n);
  Name := 'Form' + IntToStr(n); --> hier kommt der Fehler
  Visible := True;
 end;
 FListe.Add(aForm);
end;


Mfg

Moderiert von user profile iconMotzi: Code- durch Delphi-Tags ersetzt.
Inferno
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 76



BeitragVerfasst: Mi 18.08.04 14:03 
Jo is klar weil schau mal was du gemacht hast:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
procedure TFormMain.FileForm1Execute(Sender: TObject);
var
 aForm : pForm;
 n     : integer;
begin
 n := 0// <--- Du setzt "n" hier immer auf 0 dem zu folge wird auch da unten immer der              
         // selbe wert reingesetzt, in dem fall 1
 FListe := TList.Create;
 GetMem(aForm, SizeOf(TForm));
 aForm^ := TForm.CreateNew(Application);
 with aForm^ do
 begin
  inc(n);
  Caption := 'Form ' + IntToStr(n);
  Name := 'Form' + IntToStr(n); --> hier kommt der Fehler
  Visible := True;
 end;
 FListe.Add(aForm);
end;


Um weiter Formulare zu erstellen musst du ja immer die procedure ausfüllen, d.h. n wird immer mit 0 initialisiert und um 1 erhöht hat also immer den wert 1 ander stelle wo du es brauchst, deswegen heißt jede Form "Form1".

Aus diesem Grund hatte ich n als globale Var deklariert damit der wert nicht verloren geht wenn du die Procedure verläßt, demzufolge bringt es auch nix die Zeile bei dir rauszunehmen. ;)
deklariere n einfach wieder als global und nimm die Zeile n := 0; raus dann sollte es funktionieren ;)

mfg
Inferno
BigBossMan Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 32



BeitragVerfasst: Mi 18.08.04 14:14 
Inferno hat folgendes geschrieben:
Jo is klar weil schau mal was du gemacht hast:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
procedure TFormMain.FileForm1Execute(Sender: TObject);
var
 aForm : pForm;
 n     : integer;
begin
 n := 0// <--- Du setzt "n" hier immer auf 0 dem zu folge wird auch da unten immer der              
         // selbe wert reingesetzt, in dem fall 1
 FListe := TList.Create;
 GetMem(aForm, SizeOf(TForm));
 aForm^ := TForm.CreateNew(Application);
 with aForm^ do
 begin
  inc(n);
  Caption := 'Form ' + IntToStr(n);
  Name := 'Form' + IntToStr(n); --> hier kommt der Fehler
  Visible := True;
 end;
 FListe.Add(aForm);
end;


Um weiter Formulare zu erstellen musst du ja immer die procedure ausfüllen, d.h. n wird immer mit 0 initialisiert und um 1 erhöht hat also immer den wert 1 ander stelle wo du es brauchst, deswegen heißt jede Form "Form1".

Aus diesem Grund hatte ich n als globale Var deklariert damit der wert nicht verloren geht wenn du die Procedure verläßt, demzufolge bringt es auch nix die Zeile bei dir rauszunehmen. ;)
deklariere n einfach wieder als global und nimm die Zeile n := 0; raus dann sollte es funktionieren ;)

mfg
Inferno


Leider ist es noch immer der selbe Fehler. Habe die Zeile n := 0 rusgenommen und n global deklariert.

ausblenden Quelltext
1:
2:
3:
var
  FormMain: TFormMain;
  n: integer;


Wenn das hier richtig ist, oder muß es im public teil rein ?

Mfg
Inferno
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 76



BeitragVerfasst: Mi 18.08.04 14:17 
haste auch die deklaration in der procedure rausgenommen, weil die dann erstmal vorrang hätte? hatte ich vergessen zu sagen :)

Am besten gehst mal im schrittbetrieb durch und schaust mal was der fürn nen namen zuweisen will. weil mehr kann ich jetzt nich dazu sagen.

mfg
Inferno
Inferno
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 76



BeitragVerfasst: Mi 18.08.04 14:40 
Ganz wichtig auch beim beenden die erzeugten formulare wieder freizugeben, ungefähr so:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure FreeForms();
var i : integer;
    aForm : pForm;
begin
  if Liste <> nil then
  begin
    if Liste.Count >= 0 then
    begin
      for i := 0 to Liste.Count - 1 do
      begin
        aForm := Liste.Items[i];
        aForm^.Free; // Formular freigeben
      end;
    end;
    Liste.Free;  // Liste Freigeben
  end;
end;


hatte ich vergessen aber hast du ja vielleicht selber mitbekommen ;)

mfg
Inferno
BigBossMan Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 32



BeitragVerfasst: Mi 18.08.04 15:25 
Inferno hat folgendes geschrieben:
Ganz wichtig auch beim beenden die erzeugten formulare wieder freizugeben, ungefähr so:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure FreeForms();
var i : integer;
    aForm : pForm;
begin
  if Liste <> nil then
  begin
    if Liste.Count >= 0 then
    begin
      for i := 0 to Liste.Count - 1 do
      begin
        aForm := Liste.Items[i];
        aForm^.Free; // Formular freigeben
      end;
    end;
    Liste.Free;  // Liste Freigeben
  end;
end;


hatte ich vergessen aber hast du ja vielleicht selber mitbekommen ;)

mfg
Inferno


Hat jetzt alles geklappt. Danke nochmal.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure TFormMain.FileForm1Execute(Sender: TObject);
begin
 FListe := TList.Create;
 GetMem(aForm, SizeOf(TForm));
 aForm^ := TForm.Create(Application);
 with aForm^ do
 begin
  inc(fm);
  Caption := 'Form ' + IntToStr(fm);
  Name := 'Form' + IntToStr(fm+1); <span style="font-weight: bold">--> habes um 1 erhöht</span>
  Visible := True;
 end;
 FListe.Add(aForm);
end;


Mfg

Moderiert von user profile iconMotzi: Code- durch Delphi-Tags ersetzt.
Inferno
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 76



BeitragVerfasst: Mi 18.08.04 15:32 
BigBossMan hat folgendes geschrieben:
Inferno hat folgendes geschrieben:
Ganz wichtig auch beim beenden die erzeugten formulare wieder freizugeben, ungefähr so:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure FreeForms();
var i : integer;
    aForm : pForm;
begin
  if Liste <> nil then
  begin
    if Liste.Count >= 0 then
    begin
      for i := 0 to Liste.Count - 1 do
      begin
        aForm := Liste.Items[i];
        aForm^.Free; // Formular freigeben
      end;
    end;
    Liste.Free;  // Liste Freigeben
  end;
end;


hatte ich vergessen aber hast du ja vielleicht selber mitbekommen ;)

mfg
Inferno


Hat jetzt alles geklappt. Danke nochmal.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure TFormMain.FileForm1Execute(Sender: TObject);
begin
 FListe := TList.Create;    // <- Böse Falle *ggg* siehe weiter unten
 GetMem(aForm, SizeOf(TForm));
 aForm^ := TForm.Create(Application);
 with aForm^ do
 begin
  inc(fm);
  Caption := 'Form ' + IntToStr(fm);
  Name := 'Form' + IntToStr(fm+1); <span style="font-weight: bold">--> habes um 1 erhöht</span>
  Visible := True;
 end;
 FListe.Add(aForm);
end;


Mfg


Ähm, ja wenn du das so machst wird bei jedem durchlauf ne neue Liste angelegt und somit sind alle daten der alten liste weg, d.h. du kommst auch ned mehr an die formulare ran. Ich glaube sowas nennt man memory leak :?:
Is ned so praktisch, mach das Create lieber zum Beispiel in FormCreate und das freigeben zb. in FormClose.

nur so als kleiner tipp ;)

mgf
Inferno


Zuletzt bearbeitet von Inferno am Mi 18.08.04 15:42, insgesamt 1-mal bearbeitet
BigBossMan Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 32



BeitragVerfasst: Mi 18.08.04 15:41 
Inferno hat folgendes geschrieben:
BigBossMan hat folgendes geschrieben:
Inferno hat folgendes geschrieben:
Ganz wichtig auch beim beenden die erzeugten formulare wieder freizugeben, ungefähr so:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
procedure FreeForms();
var i : integer;
    aForm : pForm;
begin
  if Liste <> nil then
  begin
    if Liste.Count >= 0 then
    begin
      for i := 0 to Liste.Count - 1 do
      begin
        aForm := Liste.Items[i];
        aForm^.Free; // Formular freigeben
      end;
    end;
    Liste.Free;  // Liste Freigeben
  end;
end;


hatte ich vergessen aber hast du ja vielleicht selber mitbekommen ;)

mfg
Inferno


Hat jetzt alles geklappt. Danke nochmal.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure TFormMain.FileForm1Execute(Sender: TObject);
begin
 FListe := TList.Create;    // <- Böse Falle *ggg* siehe weiter unten
 GetMem(aForm, SizeOf(TForm));
 aForm^ := TForm.Create(Application);
 with aForm^ do
 begin
  inc(fm);
  Caption := 'Form ' + IntToStr(fm);
  Name := 'Form' + IntToStr(fm+1); <span style="font-weight: bold">--> habes um 1 erhöht</span>
  Visible := True;
 end;
 FListe.Add(aForm);
end;


Mfg


Ähm, ja wenn du das so machst wird bei jedem durchlauf ne neue Liste angelegt oder?
Is ned so praktisch, mach das Create lieber zum Beispiel in FormCreate und das freigeben zb. in FormClose.

nur so als kleiner tipp ;)

mgf
Inferno


Danke für den Tip.

Mfg