Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Eine Form mehrmals aufrufen (https://www.delphipraxis.net/109999-eine-form-mehrmals-aufrufen.html)

Tim Henford 11. Mär 2008 13:00


Eine Form mehrmals aufrufen
 
Hallo,

irgendwie steck ich grad fest:
Ich hab eine Form erzeugt, die auf Knopfdruck erstellt wird:

Delphi-Quellcode:
Form1:

unit unit1;

interface

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

type
  TForm1 = class(TForm)
    Button1: TButton;
...
dann im hauptfenster meines Projekts will ich diese Form mehrmals aufrufen, wie kann man das machen:
Eine Instanz erstelle ich so:
Delphi-Quellcode:
      Form1:= TForm.Create(nil);
      Form1.Left:= pos.X; Form1.Top:= pos.Y;
      Form1.ShowModal;
      Form1.Free;
Wie könnt ich das machen?

vsti 11. Mär 2008 13:09

Re: Eine Form mehrmals aufrufen
 
Mit

Delphi-Quellcode:
Application.CreateForm(TForm1,Form1);
Form1.Show;
solltes du die Form mehrmals createn können.

defede 11. Mär 2008 13:09

Re: Eine Form mehrmals aufrufen
 
Delphi-Quellcode:
var
  i : Integer;
  aForm : TForm;
begin
  for i:=0 to 3 do begin
    aForm := TForm1.Create(self);
    aForm.ShowModal;
  end;
...
Dann ist jedesmal aForm eine Intstanz.
Das geht :stupid:

Jelly 11. Mär 2008 13:11

Re: Eine Form mehrmals aufrufen
 
Dann erstellst du halt noch eine Instanz... Das darf natürlich nicht über die gleiche Instanzvariable Form1 gehen.... Form1 ist eh ein blöder Name.

Wenn jede Form für sich arbeitet, brauchst du dir überhaupt keinen Namen merken, dann geht das auch so:

Delphi-Quellcode:
with TForm.Create(nil) do begin
      Left:= pos.X;
      Top:= pos.Y;
      Show;  // kein Showmodal
      Free;
end ;
wichtig ist, dass du die Form über Show aufrufst, da du sonst erst eine 2. Instanz erstellen kannst, nachdem du die erste Form geschlossen hast.

Wenn du von aussen eine liste aller gezeigten Forms benötigst, dann musst du die halt in einem array oder ObjectList verwalten. Dabei bietet sich Objectlist in diesem Fall wirklich an, weil die Instanz aus der Liste entfernt wird, sobald dein Form zerstört wird.

sirius 11. Mär 2008 13:21

Re: Eine Form mehrmals aufrufen
 
Zitat:

Zitat von Jelly
Dabei bietet sich Objectlist in diesem Fall wirklich an, weil die Instanz aus der Liste entfernt wird, sobald dein Form zerstört wird.

TComponentList IHMO wäre besser, falls das Objekt von woanders freigegeben wird.

dfried 11. Mär 2008 13:25

Re: Eine Form mehrmals aufrufen
 
Zitat:

Zitat von Jelly
Delphi-Quellcode:
with TForm.Create(nil) do begin
      Left:= pos.X;
      Top:= pos.Y;
      Show;  // kein Showmodal
      Free;
end ;

Das wird nicht funktionieren, da das "Free;" die Form sofort wieder freigibt. Das Free sollte hierbei am besten im FormClose des jeweiligen Formulars mittels "Action := caFree;" gemacht werden.

Muetze1 11. Mär 2008 17:19

Re: Eine Form mehrmals aufrufen
 
... oder es wird statt Free von aussen Delphi-Referenz durchsuchenRelease aufgerufen.

Jelly 11. Mär 2008 18:16

Re: Eine Form mehrmals aufrufen
 
Zitat:

Zitat von dfried
Das wird nicht funktionieren, da das "Free;" die Form sofort wieder freigibt.

:wall: :wall: Natürlich nicht... Sowas aber auch :stupid:
Dein Vorschlag hingegen funktioniert natürlich..

Tim Henford 12. Mär 2008 09:58

Re: Eine Form mehrmals aufrufen
 
Danke für die schnellen Hilfen.

Also ich lasse die Forms jetzt folgendermaßen erstellen:
Delphi-Quellcode:
var
  formen     : array [1..5] of TForm1;
  AnzForm    : integer;

procedure THauptForm.StartBtnClick(Sender: TObject);
begin
      AnzForm:= AnzForm+1;

      formen[AnzForm]:= TForm1.Create(nil);
      formen[AnzForm].Left:= pos.X; formen[AnzForm].Top:= pos.Y;
      formen[AnzForm].Tag:= AnzForm;
      formen[AnzForm].Show;
end;
Form1 sieht dann so aus, die nächsten Fenster sollen sich alle neben das erste Reihen und wenn sich das erste bewegt sollen alle mitziehen:

Delphi-Quellcode:
...
  private
    procedure WMMove(var Message: TWMMove); MESSAGE WM_MOVE;
    procedure AlignForm;

....

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  AnzForm:= AnzForm-1;
end;

procedure TForm1.WMMove(var Message: TWMMove);
begin
  inherited;
  try    // hier hängt er dann
    if Assigned(formen[Form1.Tag]) then begin
        AlignForm;
    end;
  except
  end;
end;

procedure TForm1.AlignForm;
begin
  formen[Form1.Tag].Left := formen[formen[Form1.Tag]-1].Left + formen[formen[Form1.Tag]-1].Width;
  formen[Form1.Tag].Top := formen[formen[Form1.Tag]-1].Top;
end;
das zugreifen auf "Tag" funktioniert hier so nicht, hat da jemand eine Lösung

mkinzler 12. Mär 2008 10:07

Re: Eine Form mehrmals aufrufen
 
Besser
Delphi-Quellcode:
formen[AnzForm]:= TUmbauten.Create(self);
Warum form1? das ist eine bestimmte Referenz, welche in deinem Fall höchstwahrscheinlich Nil ist.
Besser Self.Tag bzw. Tag

Muetze1 12. Mär 2008 10:08

Re: Eine Form mehrmals aufrufen
 
Zitat:

Zitat von Tim Henford
Also ich lasse die Forms jetzt folgendermaßen erstellen:
Delphi-Quellcode:
var
  formen     : array [1..5] of TForm1;
  AnzForm    : integer;

procedure THauptForm.StartBtnClick(Sender: TObject);
begin
      AnzForm:= AnzForm+1;

      formen[AnzForm]:= TUmbauten.Create(nil);
      formen[AnzForm].Left:= pos.X; formen[AnzForm].Top:= pos.Y;
      formen[AnzForm].Tag:= AnzForm;
      formen[AnzForm].Show;
end;

- Und wenn ich den StartBtn 6x drücke?
- Wieso definierst du ein Array mit TForm1 Elementen um dann TUmbauten zu zu weisen? Warum nicht gleiche ein Array mit TUmbauten?

Zitat:

Zitat von Tim Henford
Form1 sieht dann so aus, die nächsten Fenster sollen sich alle neben das erste Reihen und wenn sich das erste bewegt sollen alle mitziehen:

Delphi-Quellcode:
...
  private
    procedure WMMove(var Message: TWMMove); MESSAGE WM_MOVE;
    procedure AlignForm;

....

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  AnzForm:= AnzForm-1;
end;

procedure TForm1.WMMove(var Message: TWMMove);
begin
  inherited;
  try    // hier hängt er dann
    if Assigned(formen[Form1.Tag]) then begin
        AlignForm;
    end;
  except
  end;
end;

procedure TForm1.AlignForm;
begin
  formen[Form1.Tag].Left := formen[formen[Form1.Tag]-1].Left + formen[formen[Form1.Tag]-1].Width;
  formen[Form1.Tag].Top := formen[formen[Form1.Tag]-1].Top;
end;
das zugreifen auf "Tag" funktioniert hier so nicht, hat da jemand eine Lösung

- Du prüfst mit assigned() auf <> nil in der WMMove Botschaftsbehandlung, aber setzt nirgendwo beim Schließen einer Form deren Eintrag auf nil.
- Du fragst den Tag ab - aber wo setzt du diesen denn? Tag ist standardmäßig 0 und von daher ist der Zugriff auf dein formen[] Array ungültig mit einem Index von 0. Das du noch fragst warum das nicht klappt, zeigt mir, dass du die Bereichs- und Überlaufprüfung nicht eingeschaltet hast in dem Projekt. Bitte hole dies sofort nach (Projektoptionen -> Compiler) und erstelle das Projekt komplett neu.
- Du benutzt excessiv Form1, somit stellt sich für mich die Frage, ob diese globale Variable überhaupt eine gültige Instanz hat.
- Warum fragst du in der WMMove Botschaftsbehandlung nicht ab, ob du dich überhaupt in der Form1 befindest, oder willst du alle Fenster als gesamtes Verschieben, egal welches gezogen wird? Wenn ja, dann musst du den Code überarbeiten.
- Du greifst bei AlignForm immer auf den Form1.Tag-ten Eintrag in dem formen[] Array zu. Aber ich dachte die Methode soll auch alle anderen Formulare nachziehen - wo geschieht dies? So kommt es mir so vor, als wenn du in der AlignForm alle Zugriffe auf "formen[Form1.Tag]" mit "Self" ersetzen könntest.

/EDIT: roter Kasten?


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:08 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz