Autor |
Beitrag |
Mathematiker
      
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: 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.
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
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
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
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: 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
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
Für diesen Beitrag haben gedankt: Mathematiker
|
|
Mathematiker 
      
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Do 01.08.13 22:24
Hallo,
IhopeonlyReader hat folgendes geschrieben : | 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.
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
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: 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
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
Mathematiker 
      
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Do 01.08.13 22:29
Alle drei Möglichkeiten:
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
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: 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
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
Mathematiker 
      
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Do 01.08.13 22:39
_________________ Töten im Krieg ist nach meiner Auffassung um nichts besser als gewöhnlicher Mord. Albert Einstein
|
|
IhopeonlyReader
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: Do 01.08.13 22:41
Tform(reference).showmodal
Oder
(Reference as tform).showmodal
?
_________________ Sucht "neueres" Delphi
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
Für diesen Beitrag haben gedankt: Mathematiker
|
|
Mathematiker 
      
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Do 01.08.13 22:44
Hallo,
Das war es. Danke!
Mit
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
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Do 01.08.13 23:45
Sauberer und einfacher geht es so: 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;
ShowForm(TForm266); | // EDIT:
Übrigens geht auch so etwas: 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); end;
procedure TForm265.Button1Click(Sender: TObject); begin ShowForm('TForm266'); end; |
Für diesen Beitrag haben gedankt: Mathematiker
|
|
Mathematiker 
      
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: 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
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
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: Fr 02.08.13 00:00
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| With aformclass.create(Nil) Do 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
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
Mathematiker 
      
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: 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
Delphi-Quelltext 1: 2: 3:
| finteraktiv.width:=formx; finteraktiv.height:=formy; finteraktiv.caption:=aktuellname2; | Werte des Formulars geändert. Verwende ich
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
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: Fr 02.08.13 00:12
Hast du meins probiert?
Oft gibt es Probleme mit abstrakten Klassen..,
_________________ Sucht "neueres" Delphi
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
Mathematiker 
      
Beiträge: 2622
Erhaltene Danke: 1447
Win 7, 8.1, 10
Delphi 5, 7, 10.1
|
Verfasst: Fr 02.08.13 00:22
Hallo,
Delphi-Quelltext 1: 2: 3: 4: 5: 6:
| With aformclass.create(Nil) Do 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
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: 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
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
Für diesen Beitrag haben gedankt: Mathematiker
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 02.08.13 06:49
IhopeonlyReader hat folgendes geschrieben : | 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...
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: 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
      
Beiträge: 600
Erhaltene Danke: 23
Delphi 7 PE
|
Verfasst: 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
Wer nicht brauch was er hat, brauch auch nicht was er nicht hat!
|
|
jaenicke
      
Beiträge: 19312
Erhaltene Danke: 1747
W11 x64 (Chrome, Edge)
Delphi 11 Pro, Oxygene, C# (VS 2022), JS/HTML, Java (NB), PHP, Lazarus
|
Verfasst: Fr 02.08.13 22:37
IhopeonlyReader hat folgendes geschrieben : | 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
      
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Fr 02.08.13 22:50
Mathematiker hat folgendes geschrieben : | 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:
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
|
|