Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Die Delphi-IDE (https://www.delphipraxis.net/62-die-delphi-ide/)
-   -   Verständnisfrage Formulardatei (https://www.delphipraxis.net/179565-verstaendnisfrage-formulardatei.html)

schöni 16. Mär 2014 21:19

Verständnisfrage Formulardatei
 
Hallo,

ich habe soeben den Kommandozeilencompiler aufgerufen, mit den Dateien Project1 (und Unit1), und habe das Phänomen, das ich ohne die dfm Datei mein Projekt nicht korrekt übersetzt bekomme. Ich erhalte zwar eine .exe Datei, die aber dann nur ein Konsolenfenster zeigt.

Project1 enthält das für Windows GUI übliche und Unit1 die leere TForm1 Klasse, aber experimentell ohne die Anweisung {*.dfm} Daher auch das seltsame Verhalten.

Ich hätte ein leeres Windows Fenster erwartet. Aber meine Überlegung sagt mir, das die Formularressource ja mindestens die Ausdehnung des Formulars enthalten muss und die Fensterstil Angaben. Die fehlen natürlich, wenn ich die Ressourcendatei weglasse.

Wenn ich aber das Fenster per CreateWindowEx() erzeuge, erwartet diese Funktion nahezu komplett andere Angeben, als die die mindestens in der .dfm Datei stehen, wenn keine andere Komponente auf dem Formular liegt. Was muss ich also machen, um ohne die Anweisung {*.dfm} in Unit1 das leere Fenster zu erhalten und warum muss ich das dann so machen.

Was also läuft innerhalb des Übersetzungsvorgangs mit der Formulardatei ab?

- Wird implizit ein DfmToPas ausgeführt und dann erst übersetzt oder
- wird die .dfm Datei als Ressource in die .exe einkompiliert { ich nehme an, die Ressource wird einkompiliert}

Wenn letzteres, lässt sich das ändern?

Wie also erreiche ich, das das leere Fenster erzeugt wird? Denn da die Funktion CreateWindowEx() ja andere Angaben fordert, als die in meinem Konstrukt fehlenden, muss es ja schon einen implziten Aufruf dieser Funktion innerhalb TForm geben. Wie also kann ich die fehlenden Angeban mit Laufzeitquelltext ergänzen.

himitsu 16. Mär 2014 22:39

AW: Verständnisfrage Formulardatei
 
Es wird immer eine DFM-Resource benötigt, wenn man eine VCL-TForm laden will.

Im Constructor von TForm wird immer eine Resource gesucht, mit dem Namen der Klasse, wenn es ein Nachfahre von TForm ist.

Und eigentlich sollte beim Fehlen eine Exception auftreten, sobald man die Form erstellen will, da diese Resource nicht gefunden wird.

dataspider 17. Mär 2014 06:03

AW: Verständnisfrage Formulardatei
 
Zitat:

Zitat von himitsu (Beitrag 1252190)
Es wird immer eine DFM-Resource benötigt, wenn man eine VCL-TForm laden will.

Ich erstelle auch Formulare im Code ohne DFM - Datei.
Man muss dann nur den Constructor CreateNew aufrufen.

Ob das allerdings auch z.B. mit dem MainForm funktioniert, habe ich noch nicht probiert.

Frank

schöni 17. Mär 2014 18:52

AW: Verständnisfrage Formulardatei
 
Soooo, ich hab das jetzt mal durchgetestet. Weder die Ableitung TForm1 von TCustomForm noch die von TScrollingWinControl noch die von TWinControl funktioniert mit nur CreateNew ohne .dfm Datei.

Zitat:

Zitat von himitsu
Und eigentlich sollte beim Fehlen eine Exception auftreten, sobald man die Form erstellen will, da diese Resource nicht gefunden wird.

Sehe ich inzwischen auch so. Die Exception kommt aber nicht. Stattdessen blitzt kurz das Konsolenfenster auf und dann schließt sich das Programm. SO klappt das also gar nicht.

Habe aber verstanden, das TForm so konstruiert ist, das da halt die .dfm Datei als Ressource zwingend vorausgesetzt wird.

Wie aber könnte nun am einfachsten dieses Verhalten geändert werden? der CreateNew Konstruktor ist definitiv nicht genug. Weiß jemand Rat oder gaht das dann wirklich nur "zu Fuß" per CreateWindowEx()?

Ich vermute dies mittlerweile, werde weiter experimentieren.

himitsu 17. Mär 2014 19:11

AW: Verständnisfrage Formulardatei
 
Wenn man eine leere Form direkt als TForm.Create erstellt, also nicht über eine Ableitung, dann braucht an keine DFM-Resource oder muß nicht die Laderoutine "umgehen".

Vielleicht denkt die Fehlerbehandlung die Anwendung wäre eine "Konsolenanwendung", wenn in diesem Fall schon mitten im Erstellen des ersten VCL-Fensters knallt?

Du könntest die Anwendung mal von der Konsole aus starten, eventuell kann man da dann eine Fehlermeldung erkennen.
Oder schrittweise die VCL debuggen und dabei eine Pause einlegen, solange das kurzzeitige Konsolenfenster da ist ... eventuell kann man dann dort drin ja was lesen.

dataspider 17. Mär 2014 19:25

AW: Verständnisfrage Formulardatei
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von schöni (Beitrag 1252307)
Soooo, ich hab das jetzt mal durchgetestet. Weder die Ableitung TForm1 von TCustomForm noch die von TScrollingWinControl noch die von TWinControl funktioniert mit nur CreateNew ohne .dfm Datei.

Ich habe ein Mini - Projekt mit Form ohne DFM - Datei angehangen.
Aber vielleicht habe ich etwas falsch verstanden.

Frank

schöni 17. Mär 2014 20:06

AW: Verständnisfrage Formulardatei
 
Hmmm, nun ja, das hier sagt zunächst mal die Hilfe von Delphi 7 zu CreateNew:
Zitat:

CreateNew sollte anstelle des Konstruktors Create verwendet werden, wenn Sie ein Formular erzeugen wollen, ohne dass es in der zugehörigen .DFM-Datei initialisiert wird. Verwenden Sie CreateNew immer dann, wenn der Nachkomme von TCustomForm kein TForm-Objekt oder kein Nachkomme von TForm ist.

CreateNew umgeht das Einlesen der zuvor zugewiesenen .DFM-Datei. Enthält das Formular visuelle Komponenten, müssen Sie deshalb eine externe .DFM-Datei einlesen, um die visuellen Komponenten an ihre Klassen zu binden. Verfügt das neue Formularobjekt über eine externe .DFM-Datei, rufen Sie nach CreateNew die Methode InitInheritedComponent auf. Wenn Sie die .dfm-Datei für die neue Formularinstanz erstellen müssen, schließen Sie den Aufruf von CreateNew in WriteComponentResFile- und ReadComponentResFile-Aufrufe ein. Die folgende Code-Sequenz

1. schreibt eine externe .DFM-Datei, erstellt ein neues Formular, das nicht an eine .DFM-Ressourcendatei gebunden ist, und liest eine externe .DFM-Datei ein und bindet sie an das neue Formular:

WriteComponentResFile('Temp.dfm', Form1);
...
Form2 := TForm.CreateNew(Application);
ReadComponentResFile('Temp.dfm', Form2);

Warnung Die Verwendung von CreateNew anstelle von Create kann zu unvorhersehbaren Ergebnissen führen, da die meisten Formulare unter der Voraussetzung geschrieben werden, dass ihre Steuerelemente in der .DFM-Datei erzeugt werden.
Wenn ich statt Application.CreateForm(TForm1, Form1); -> Form1 := TForm1.Create(Application); schreibe, wird das Formular bei mir nicht korrekt angezeigt, wenn die .dfm Datei fehlt.

Zitat:

Zitat von dataspider alias Frank
Ich habe ein Mini - Projekt mit Form ohne DFM - Datei angehangen.
Aber vielleicht habe ich etwas falsch verstanden.

Ok, Danke, ich werde mir das mal anschauen und auch debuggen.
Ohne .dfm ist aber auf jeden Fall richtig, genau das will ich ja testen und ggf. verstehen warum das evtl. nicht klappt.
Die Exception kommt korrekt innerhalb der IDE aber nicht außerhalb, wenn ich das Formular mit Create() initialisiere aber nicht in Turbo Delphi. Wenn mit CreateNew() initialisiert, kommt auch in der IDE keine Exception, obwohl das Formular auch dann nicht korrekt aufgebaut wird.

Ich fürchte, dann wird das was ich erreichen will wohl nur per WinAPI gehen. Der Formularaufruf komplett ohne .dfm Datei.

VCL Debug ergibt, das MainForm nicht initialisiert wird, trotz CreateNew.

Delphi-Quellcode:
begin
  Application.Initialize;
  //Application.CreateForm(TForm1, Form1);
  Form1 := TForm1.CreateNew(Application);
  Form1.ShowModal;
  Application.Run;
end.

Wenn ich hier Form1.ShowModal aufrufe, bekomme ich das Formular korrekt angezeigt, nicht aber mit Form.Show. Letztere Anweisung lässt das Formular nur kurz aufblitzen, dann verschwindet das Formular wieder und das Programm beendet sich. Nur ShowModal funktioniert hier.

Aber warum. Debug ergibt hier in TApplication.Run, das FMainForm = NIL ist. Warum funktioniert dann ShowModal überhaupt? (confused). Show lässt immerhin das Formular aufblitzen. Aber wenn FMainform = NIL ist, dürfte doch gar keins angezeigt werden, schon gar nicht permanent, wie das mit ShowModal jedoch der Fall ist.

Zum Verständnis der Methoden Show und ShowModal brauche ich länger. Dort muss ja der Schlüssel für das oben genannte Verhalten liegen.

Wenn ich Debugge und das mit ShowModal angezeigte Formular während das Debuggens schließe, verabschiedet sich übrigens die IDE.

Habe das sowohl mit Turbo Delphi als auch mit Delphi 7 getestet.

himitsu 17. Mär 2014 20:22

AW: Verständnisfrage Formulardatei
 
Es gibt keinen Ersatz für Application.CreateForm, jedenfalls nicht, wenn es sich um die erste Form handelt, welche dabei zur MainForm wird.
Da sich die MainForm nur via CreateForm registrieren lässt und man für das Application.Run unbedingt eine MainForm braucht, kann man also Application.Run ebenfalls nicht verwenden. und Müsste auch dieses selber behandeln.

Run wird sofort beendet, wenn es keine MainForm mehr gibt.

michaelthuma 17. Mär 2014 20:41

AW: Verständnisfrage Formulardatei
 
Key Objects Library. Möglw. kannst du etwas mitnehemen in deine Implementierung. Was auch immer du da treibst :wink:

Zitat:

Zitat von schöni (Beitrag 1252324)
Ich fürchte, dann wird das was ich erreichen will wohl nur per WinAPI gehen. Der Formularaufruf komplett ohne .dfm Datei.


schöni 17. Mär 2014 21:10

AW: Verständnisfrage Formulardatei
 
Zitat:

Zitat von himitsu (Beitrag 1252326)
Es gibt keinen Ersatz für Application.CreateForm, jedenfalls nicht, wenn es sich um die erste Form handelt, welche dabei zur MainForm wird.
Da sich die MainForm nur via CreateForm registrieren lässt und man für das Application.Run unbedingt eine MainForm braucht, kann man also Application.Run ebenfalls nicht verwenden. und Müsste auch dieses selber behandeln.

Run wird sofort beendet, wenn es keine MainForm mehr gibt.

Alles Klar!

Danke noch mal allen, die hier geantwortet haben.

Dann brauche ich also die Mainform für das erste Femster auf jeden Fall und diese setzt die .dfm Datei als einzukompilierende Ressource zwingend voraus. Die Application ist ja dann auch modal, das heißt, das Hauptfenster exisitiert, bis es durch Close oder Application.Terminate beendet wird. Deshalb hat der Aufruf auch mit ShowModal nicht jedoch mit Show funktioniert.

Von einem solchen Hauptfenster aus kann ich dann ein weiteres Formular per CreateNew und Show anzeigen lassen. Dann ist also das Design in der VCL begründet, die für das erste Formular, das Hauptfenster der Anwendung die Formularressource zwingend voraussetzt. Wenn ich also von Anfang an auf die .dfm Datei verzichten will, brauche ich eine andere Klassenbibliothek. :cry:

Ok, Ich werd mir auch KOL (Key Objects Library) auf jeden Fall ansehen. Außerdem hab ich ja noch fpGUI und LPTK. Bei fpGUI weiß ich noch nicht, ob die auch mit Delphi verwendbar ist. Die kommt aus Freepascal und das unterscheidet sich ja geringfügig aber doch deutlich genug in der Syntax. LPTK funktioniert aber schon mal mit Delphi.

himitsu 17. Mär 2014 21:30

AW: Verständnisfrage Formulardatei
 
Die MainForm könnte man auch aus einer TForm generieren, welche keine Resource benötigt.
(eventuelle Subkomponenten könnte man auf der dann dynamisch erstellen)


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

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