Autor Beitrag
Mathematiker
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Do 01.08.13 22:15 
Hallo,
ich stehe wieder mal vor einem Problem, dass ich nicht lösen kann, da ich eigentlich nur mit "Versuch und Irrtum" experimentiere und die Theorie nicht kapiere.
In einem Programm habe ich sehr viele Formulare, die ich nicht zum Programmstart erzeugen möchte. Bisher rufe ich sie mit z.B.
ausblenden Delphi-Quelltext
1:
2:
3:
  Application.CreateForm(TFinteraktiv, Finteraktiv);
  finteraktiv.showmodal;
  finteraktiv.release;

auf. Das funktioniert, gefällt mir aber bei den mehr als 50 Formularen nicht. Irgendwie ist das zu "umständlich".

Deshalb dachte ich, eine allgemeine Methode zu schreiben. Meine Idee war etwas in der Art
ausblenden Delphi-Quelltext
1:
procedure aufrufen(form:tform);					

bei der ich die Bezeichnung des Formulars übergebe und in der Methode die Klasse für Createform ermittelt wird. Leider weiß ich nicht, was ich dort tun soll. Null Ahnung.

Daher habe ich es mit
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
procedure rufen(tform:tformclass; form:tform);
begin
    Application.CreateForm(tForm, Form);
    form.showmodal;
    form.release;
end;
...
  case formularnr of
   1 : rufen(TFinteraktiv, Finteraktiv);
   2 : rufen(TFanalysis, Fanalysis);
...
  end;

versucht. Und nun tritt das Problem auf. Das Programm fliegt mir bei jedem Aufruf mit einer Access Violation um die Ohren. So geht es also nicht und ich bin wieder eine Erfahrung reicher, dass ich eigentlich die Delphi-Grundlagen mal lernen müsste.
Natürlich ist mir klar, dass der Aufwand für nur je zwei gesparte Befehle je Formularaufrufe unverhältnismäßig ist, aber jetzt interessiert es mich schon aus Prinzip.
Kann mir jemand von Euch helfen? Danke.

Beste Grüße
Mathematiker

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
IhopeonlyReader
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Do 01.08.13 22:20 
Benenne doch mal tform um.. Tform ist soviel ich weiß eine Klasse und sollte nicht für eine variable missbraucht werden ;) ob das der Fehler ist weiß ich nicht

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!

Für diesen Beitrag haben gedankt: Mathematiker
Mathematiker Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Do 01.08.13 22:24 
Hallo,
user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
Benenne doch mal tform um.. Tform ist soviel ich weiß eine Klasse und sollte nicht für eine variable missbraucht werden ;)

Danke. Ich bin so blöd. :autsch: :autsch: :autsch:
Wie kann ich tform als Variable benutzen? Aber es ändert nichts am Absturz, nachdem ich tform:tformclass in xform:tformclass umbenannt habe. Leider.

Beste Grüße
Mathematiker

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
IhopeonlyReader
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Do 01.08.13 22:26 
Ein anderer Fehler könnte es sein, dass Klassen ja pointer sind.. Deshalb brauch man eig kein var davor schreiben, aber in deinem Sonderfall ist die Variable noch Nil.. Setzte deshalb mal ein var davor, da du dem
Pointer eine speicheradresse zuweist und nichts in der Klasse änderst..

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
Mathematiker Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Do 01.08.13 22:29 
Alle drei Möglichkeiten:
ausblenden Delphi-Quelltext
1:
2:
3:
procedure rufen(var xform:tformclass; var form:tform);
procedure rufen(var xform:tformclass; form:tform);
procedure rufen(xform:tformclass; var form:tform);
werden von Delphi gar nicht erst übersetzt. Schade.

Beste Grüße
Mathematiker

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
IhopeonlyReader
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Do 01.08.13 22:32 
Und wenn du die Parameter deiner procedure exakt so machst wie die Parameter von Applikation.formcreate

Wenn Du die klammer auf machst, siehst du ja was wie verlangt wird ;)

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
Mathematiker Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Do 01.08.13 22:39 
user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
Und wenn du die Parameter deiner procedure exakt so machst wie die Parameter von Applikation.formcreate

Habe ich versucht. Bei
ausblenden Delphi-Quelltext
1:
rufen(FormClass: TFormClass; var Reference)					

kann ich aber "Reference" nicht nutzen. Dann wird zwar
ausblenden Delphi-Quelltext
1:
Application.CreateForm(Formclass, reference);					
übersetzt, aber nicht
ausblenden Delphi-Quelltext
1:
2:
reference.showmodal;
reference.release;
Ich weiß wieder nicht, was ich hier eigentlich tue. :autsch:

Beste Grüße
Mathematiker

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
IhopeonlyReader
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Do 01.08.13 22:41 
Tform(reference).showmodal
Oder
(Reference as tform).showmodal
?

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!

Für diesen Beitrag haben gedankt: Mathematiker
Mathematiker Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Do 01.08.13 22:44 
Hallo,
user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
Tform(reference).showmodal

Das war es. Danke!
Mit
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure rufen(FormClass: TFormClass; var Reference);
begin
    Application.CreateForm(Formclass, reference);
    tform(reference).showmodal;
    tform(reference).release;
end;
klappt alles wunderbar. Allerdings muss ich jetzt mal noch sehen, ob mehrere Formulare aufrufbar sind und was FastMM4 dazu sagt.

Beste Grüße
Mathematiker

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Do 01.08.13 23:45 
Sauberer und einfacher geht es so:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
procedure ShowForm(const AFormClass: TFormClass);
var
  MyForm: TForm;
begin
  MyForm := AFormClass.Create(nil);
  try
    MyForm.ShowModal;
  finally
    MyForm.Free;
  end;
end;

// Aufruf:
  ShowForm(TForm266);
// EDIT:
Übrigens geht auch so etwas:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
procedure ShowForm(const AFormClass: String);
var
  MyForm: TForm;
begin
  MyForm := TFormClass(FindClass(AFormClass)).Create(nil);
  try
    MyForm.ShowModal;
  finally
    MyForm.Free;
  end;
end;

procedure TForm265.FormCreate(Sender: TObject);
begin
  RegisterClass(TForm266); // Da die Klasse sonst nirgends benutzt wird, muss sie registriert werden...
end;

procedure TForm265.Button1Click(Sender: TObject);
begin
  ShowForm('TForm266'); // ...und kann nun über den Namen als String angesprochen werden
end;

Für diesen Beitrag haben gedankt: Mathematiker
Mathematiker Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Fr 02.08.13 00:00 
Hallo jaenicke,
Danke für die Hinweise.
Ich habe beides ausprobiert und leider tritt bei beiden Varianten an den Stellen
ausblenden Delphi-Quelltext
1:
2:
3:
  MyForm := AFormClass.Create(nil);
bzw.
  MyForm := TFormClass(FindClass(AFormClass)).Create(nil);

ein Programmabsturz auf. Könnte es an meinem Delphi 5 liegen?

Beste Grüße
Mathematiker

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
IhopeonlyReader
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Fr 02.08.13 00:00 
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
With aformclass.create(NilDo
 Try
 Showmodal;
  Finally
  Free;
  End;

Ebenso möglich.. Dann würde man sich 4Byte RAM sparen ;) und müsste sich nicht mit variablen eines abstrakten klasse beschäftigen, dass oft zu Fehlern führt

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
Mathematiker Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Fr 02.08.13 00:10 
Hallo,
ich weiß, warum jaenickes Vorschlag bei mir abstürzte.
In den Methoden von TFinteraktiv habe ich z.B. mit
ausblenden Delphi-Quelltext
1:
2:
3:
    finteraktiv.width:=formx;
    finteraktiv.height:=formy;
    finteraktiv.caption:=aktuellname2;
Werte des Formulars geändert. Verwende ich
ausblenden Delphi-Quelltext
1:
2:
3:
    width:=formx;
    height:=formy;
    caption:=aktuellname2;
funktioniert es einwandfrei.

Beste Grüße
Mathematiker

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
IhopeonlyReader
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Fr 02.08.13 00:12 
Hast du meins probiert?

Oft gibt es Probleme mit abstrakten Klassen..,

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
Mathematiker Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 2622
Erhaltene Danke: 1447

Win 7, 8.1, 10
Delphi 5, 7, 10.1
BeitragVerfasst: Fr 02.08.13 00:22 
Hallo,
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
With aformclass.create(NilDo
 Try
 Showmodal;
  Finally
  Free;
  End;

ergibt ebenso Probleme, wenn ich in den Methoden Eigenschaften des Formulars in der Form finteraktiv.xxxxx:= ändern will. Ist ja eigentlich auch logisch.
Unklar ist für mich nur noch, ob ich durch das Weglassen von "finteraktiv." mit width, height, caption, ... auch wirklich immer die Eigenschaften des Formulars erhalte und nicht die von irgendeinem enthaltenen Objekt wie TPanel, TPaintbox, ...

Beste Grüße
Mathematiker

_________________
Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
IhopeonlyReader
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Fr 02.08.13 00:27 
Wenn Du das finteraktiv weglässt wird die variable Der Klasse genommen..
Auto: tauto
Pkw:tauto;

Procedure tauto.Test;
Begin
Auto.Reifen := 4;
Reifen := 5;
End;

Auto.Test dann hat Auto 5 Reifen
Pkw.Test dann hat Auto 4 Reifen und Pkw 5
Verstehst du? Aber wehe Auto wurde vor dem Aufruf von Pkw.Test nicht erzeugt..

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!

Für diesen Beitrag haben gedankt: Mathematiker
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 02.08.13 06:49 
user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
Ebenso möglich.. Dann würde man sich 4Byte RAM sparen ;) und müsste sich nicht mit variablen eines abstrakten klasse beschäftigen, dass oft zu Fehlern führt
Was du gepostet hast, ergibt exakt den gleichen Code... ob du die Variable nun explizit anlegst oder mit with versteckt ändert doch am Speicher nichts...

Und was Fehler angeht, da ist with eine der größten Fehlerquellen, die es in Delphi gibt... :roll:
Aus den Quelltexten von Delphi selbst wurde es nicht umsonst eliminiert und in der Hilfe wird von der Benutzung mittlerweile ebenfalls abgeraten.

Vor allem beim späteren Überarbeiten von Quelltexten oder schon bei einer neuen Delphiversion verursacht das massive Probleme. Denn man erkennt innerhalb eines with nicht was wozu gehört, so dass man bei einer Änderung des Quelltextes sehr aufpassen muss was man tut und teilweise trotz Aufpassen nicht so einfach sehen kann was wozu gehört. Als Beispiel hier ein Auszug aus einer älteren Version der VirtualStringTrees:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
procedure TBaseVirtualTree.StaticBackground(Source: TBitmap; Target: TCanvas; Offset: TPoint; R: TRect);
begin
...
      with DrawRect do
        MaskBlt(Target.Handle, Left - Offset.X, Top - Offset.Y, (Right - Offset.X) - (Left - Offset.X),
          (Bottom - Offset.Y) - (Top - Offset.Y), Source.Canvas.Handle, Left - PicRect.Left, DrawRect.Top - PicRect.Top,
          Source.MaskHandle, Left - PicRect.Left, Top - PicRect.Top, MakeROP4(DST, SRCCOPY));
In einer neuen Delphiversion hatte ein TRect nun plötzlich selbst eine Prozedur Offset drin und schwupps, schon bezog sich Offset durch das with nicht mehr auf den Parameter Offset, sondern auf diese Prozedur...
An der Stelle gab es zum Glück einen Fehler beim Kompilieren, aber an anderen Stellen wurde so plötzlich Width von TRect benutzt statt vom Formular, in dem man das aufgerufen hatte. Das resultierte dann in schwer zu findenden Fehlern...

Wenn ich dran denke wie viele Stunden wir bei der Arbeit schon mit with-Fehlern verbracht haben... da wird mir schlecht. Aber es dauert halt das überall nach und nach auszubauen...
IhopeonlyReader
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 600
Erhaltene Danke: 23


Delphi 7 PE
BeitragVerfasst: Fr 02.08.13 22:01 
Klappt es denn mit self. (anstatt finteraktiv oder. Ganz ohne)?
Self ist der "aufrufer" also als wenn du es weglassen würdest, falls es aber Reifen und in der Klasse tauto Reifen gibt dann verwende lieber self.Reifen in dertAuto procedure

_________________
Sucht "neueres" Delphi :D
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
jaenicke
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 19312
Erhaltene Danke: 1747

W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
BeitragVerfasst: Fr 02.08.13 22:37 
user profile iconIhopeonlyReader hat folgendes geschrieben Zum zitierten Posting springen:
Klappt es denn mit self. (anstatt finteraktiv oder. Ganz ohne)?
Nein, denn Parameter kann man damit nicht ansprechen. Es gibt in dem Fall keine andere Lösung als das with zu entfernen oder den Parameter umzubenennen. Ob dann mit dem nächsten Delphiupgrade der nächste Begriff umbenannt werden muss, weißt du aber immer noch nicht... und den umbenannten Begriff gibt es dann ggf. auch wieder.

Letztlich ist alles was den Scope unklar macht, und das tut with eben, Gift für sauberen Quelltext. Denn normalerweise ist genau geregelt in welcher Reihenfolge Begriffe gesucht werden und ob in irgendeiner Klasse oder irgendwo anders etwas dazukommt, ist egal. With sorgt dafür, dass eben diese Reihenfolge außer Kraft gesetzt werden kann.

Davon abgesehen ist der einzige Vorteil von with das Sparen von ein paar Buchstaben Schreibarbeit. Wer sich davor scheut, hat sich als Softwareentwickler schlicht den falschen Beruf ausgesucht.
jfheins
ontopic starontopic starontopic starontopic starontopic starontopic starofftopic starofftopic star
Beiträge: 918
Erhaltene Danke: 158

Win 10
VS 2013, VS2015
BeitragVerfasst: Fr 02.08.13 22:50 
user profile iconMathematiker hat folgendes geschrieben Zum zitierten Posting springen:
Hallo,
Unklar ist für mich nur noch, ob ich durch das Weglassen von "finteraktiv." mit width, height, caption, ... auch wirklich immer die Eigenschaften des Formulars erhalte und nicht die von irgendeinem enthaltenen Objekt wie TPanel, TPaintbox, ...

Solange du kein with benutzt: wahrscheinlich schon. Deine Event-Handler sehen ja meistens so ähnlich aus:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
procedure TMeinFormular.Button1Click(Sender: TObject)
begin
  showmessage(IntToStr(Width));
end;


Das Width bezieht sich nun immer auf die konkrete Instanz von TMeinFormular. Das ist ja auch eine Methode dieses Formulars, wie du daran erkennst, dass der Klassenname vor dem Methodennamen steht.
Der Parameter Sender bezieht sich hingegen auf den Button/Panel/Whatever welches das Event ausgelöst hat.

Das ändert sich natürlich in dem Moment, in dem du Methoden betrachtest die nicht zu einem Formular gehören.

Für diesen Beitrag haben gedankt: Mathematiker