AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

(Formular-)Handling größerer Projekte

Ein Thema von mm1256 · begonnen am 11. Mär 2015 · letzter Beitrag vom 13. Mär 2015
Antwort Antwort
Seite 1 von 4  1 23     Letzte »    
mm1256

Registriert seit: 10. Feb 2014
Ort: Wackersdorf, Bayern
642 Beiträge
 
Delphi 10.1 Berlin Professional
 
#1

(Formular-)Handling größerer Projekte

  Alt 11. Mär 2015, 11:42
Hallo DP-Gemeinde,

wenn eine App nur ein oder wenige Fenster hat, ist die Sache ja ziemlich einfach. Da kann man mit der Delphi-Automatik (Erzeugen der Formulare in der dpr) gut leben. Etwas anders sieht es aus, wenn die App größer wird. Hier gibt es wohl sehr unterschiedliche Ansichten, Meinungen und Praktiken. Das bringt mich zu der Frage, ob denn meine Praxis was taugt und ob man vielleicht daran noch etwas optimieren könnte?

Hintergrund meiner Frage ist auch: Ich bin gelerter Elektriker der sich das Programmieren im Selbststudium angeeignet hat. Ich hab also noch keine Uni von innen gesehen. Manchmal stelle ich mir darum die Frage, ob das was ich mache auch Stand der Technik ist. Weil, für Optimierungen muss man(n) bekanntlich immer ein offenes Ohr haben.

Generell erzeuge ich in der dpr nur die Datenmodule und das Hauptformular:

Delphi-Quellcode:
{------------------------------------------------------------------------------}
{-} {$I Project1.inc} {--------------------------------------------------------}
{------------------------------------------------------------------------------}

program Project1;

uses
  {$IFDEF DEBUG}
  FastMM4,
  {$ENDIF}
  Vcl.Forms,
  uMainForm in 'uMainForm.pas{FrmMainForm},
  uClientForm1 in 'uClientForm1.pas{FrmClient1},
  uClientForm2 in 'uClientForm2.pas{FrmClient2},
  uMainData in 'uMainData.pas{MainData: TDataModule};

{$R *.res}

begin
  {$IFDEF DEBUG}
  ReportMemoryLeaksOnShutdown := True;
  {$ENDIF}
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TMainData, MainData);
  Application.CreateForm(TFrmMainForm, FrmMainForm);
  Application.Run;
end.
Die INC sieht so aus:

Delphi-Quellcode:
{------ Standard-Compiler-Optionen --------------------------------------------}
{-----} {$A+,B+,C+,E-,F-,G+,H+,J+,K-,M-,N+,O+,P+,S-,T-,U-,V+,W-,X+,Y-,Z1} {----}
{$IFDEF DEBUG}    {$DEFINE TEST}                                        {$ENDIF}
{- Range-Check und Debug-Info wahlweise beim Testen ein/aus -------------------}
{$IFDEF TEST}     {$DEFINE UseRangeCheck} {$DEFINE CreateDebugInfo}     {$ENDIF}

{$IFDEF UseRangeCheck}
  {$Q+,R+}
{$ELSE}
  {$Q-,R-}
{$ENDIF UseRangeCheck}

{$IFDEF CreateDebugInfo}
  {$D+ L+}
  {$OPTIMIZATION   ON}
  {$DEBUGINFO      ON}
  {$LOCALSYMBOLS   ON}
  {$REFERENCEINFO  ON}
  {$DEFINITIONINFO ON}
  {$ASSERTIONS     ON}
{$ELSE}
  {$OPTIMIZATION   ON}
  {$DEBUGINFO      OFF}
  {$LOCALSYMBOLS   OFF}
  {$REFERENCEINFO  OFF}
  {$DEFINITIONINFO OFF}
  {$ASSERTIONS     OFF}
{$ENDIF CreateDebugInfo}
Das Hauptformular:

Delphi-Quellcode:
{------------------------------------------------------------------------------}
{-} {$I Project1.inc} {--------------------------------------------------------}
{------------------------------------------------------------------------------}

unit uMainForm;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TFrmMainForm = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  FrmMainForm: TFrmMainForm;

implementation

{$R *.dfm}

uses uClientForm1, uClientForm2;

procedure TFrmMainForm.Button1Click(Sender: TObject);
begin
  FrmClient1_Show;
end;

procedure TFrmMainForm.Button2Click(Sender: TObject);
begin
  case FrmClient2_ShowModal of
    mrOk : ShowMessage('OK');
    mrCancel : ShowMessage('Cancel');
  end;
end;

end.
Normales Formular (ist bei etwa 8 Formularen ein MDI-Formular)

Delphi-Quellcode:
{------------------------------------------------------------------------------}
{-} {$I Project1.inc} {--------------------------------------------------------}
{------------------------------------------------------------------------------}

unit uClientForm1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TFrmClient1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  FrmClient1: TFrmClient1 = nil;
  FrmClient1Active: boolean = false;

procedure FrmClient1_Show;

implementation

{$R *.dfm}

procedure FrmClient1_Show;
begin
  if not FrmClient1Active
  then FrmClient1 := TFrmClient1.Create(Application);
  FrmClient1.Show;
end;

procedure TFrmClient1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
  FrmClient1Active := false;
end;

procedure TFrmClient1.FormCreate(Sender: TObject);
begin
  FrmClient1Active := true;
end;

end.
Modale Formulare:

Delphi-Quellcode:
{------------------------------------------------------------------------------}
{-} {$I Project1.inc} {--------------------------------------------------------}
{------------------------------------------------------------------------------}

unit uClientForm2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;

type
  TFrmClient2 = class(TForm)
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

function FrmClient2_ShowModal: integer;

implementation

{$R *.dfm}

function FrmClient2_ShowModal: integer;
begin
  with TFrmClient2.Create(Application) do
  try
    Result := ShowModal;
  finally
    Release;
  end;
end;

end.
Detail-Fragen:

1) Gibt es hinsichtlich einer optimalen Exe-Größe bei der Include-Datei noch Optimierungsmöglichkeiten?

2) Bei den normalen und MDI-Fenstern würde ich gerne die globalen Variablen lokal machen, also im implemantation-Teil, damit der versehentliche Zugriff aus dem Hauptformular bzw. auch anderen Formularen (wenn ein untergeordnetes Formular wiederum ein weiteres Formular aufruft) ausgeschlossen ist. Ich habe es testweise mal probiert und keine Nebenwirkungen festgestellt.

oder

3) Macht es Sinn, die Boolean-Variablen weg zu lassen, und stattdessen auf NIL zu prüfen? Wenn ja, wie geht das zuverlässig? Stichwort mögliche Exceptions beim Anzeigen oder Schließen.

Ich möchte in jedem Fall wie bisher den Speicher beim Beenden eines Formulares wieder frei geben denn es befinden sich insgesamt über 100 Formulare im Projekt.

Vielen Dank schon mal für eure Anregungen.
Gruss Otto PS: Sorry wenn ich manchmal banale Fragen stelle. Ich bin Hobby-Programmierer und nicht zu faul die SuFu zu benutzen
  Mit Zitat antworten Zitat
Benutzerbild von Nersgatt
Nersgatt

Registriert seit: 12. Sep 2008
Ort: Emlichheim
693 Beiträge
 
Delphi 10.1 Berlin Professional
 
#2

AW: (Formular-)Handling größerer Projekte

  Alt 11. Mär 2015, 11:51
Zu 1) weiß ich nicht.
zu 2) Man sollte Variablen immer so lokal wie möglich deklarieren. Von daher ist das eine gute Idee
zu 3) Du kannst mit Assigned(FrmClient1) prüfen, ob die Variable zugewiesen ist. Dabei solltest Du aber beim Freigeben des Formulars FreeAndNil(FrmClient1) nutzen. Dann funktioniert das zuverlässig und Du kannst die Boolschen Variablen einsparen. Der Fachbegriff für das, was Du da machst, ist übrigens "lazy initialization"

Die Vorgehensweise beim Modalen Formular kannst Du so machen. Ich würde es etwas anders schreiben (lokale Variable für die Instanz deklarieren und das with weglassen), das ist hier im Endeffekt egal.
Jens

Geändert von Nersgatt (11. Mär 2015 um 11:55 Uhr)
  Mit Zitat antworten Zitat
mm1256

Registriert seit: 10. Feb 2014
Ort: Wackersdorf, Bayern
642 Beiträge
 
Delphi 10.1 Berlin Professional
 
#3

AW: (Formular-)Handling größerer Projekte

  Alt 11. Mär 2015, 12:00
zu 3) Du kannst mit Assigned(FrmClient1) prüfen, ob die Variable zugewiesen ist. Dabei solltest Du aber beim Freigeben des Formulars FreeAndNil(FrmClient1) nutzen.....
Mit Assigned(FrmClient1) und FreeAndNil(FrmClient1) habe ich ja ursprünglich beim Erstellen der Formulare (ist schon 10+ Jahre her) rum gespielt und es hat immer wieder geknallt. Die Frage ist, an welcher Stelle (welchem Formular-Event) soll man "FreeAndNil" denn verwenden, damit es bei normalen und MDI-Fenstern gleichermaßen funzt.
Gruss Otto PS: Sorry wenn ich manchmal banale Fragen stelle. Ich bin Hobby-Programmierer und nicht zu faul die SuFu zu benutzen
  Mit Zitat antworten Zitat
bcvs

Registriert seit: 16. Jun 2011
703 Beiträge
 
Delphi 12 Athens
 
#4

AW: (Formular-)Handling größerer Projekte

  Alt 11. Mär 2015, 12:30
Die Frage ist, an welcher Stelle (welchem Formular-Event) soll man "FreeAndNil" denn verwenden, damit es bei normalen und MDI-Fenstern gleichermaßen funzt.
Ich mache im Prinzip sowas:
Delphi-Quellcode:
procedure TFrmClient1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
  FrmClient1:=nil;
end;
Also kein FreeAndNil, denn das Free wird ja automatisch durch das Action:=caFree ausgelöst.
  Mit Zitat antworten Zitat
Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.186 Beiträge
 
Delphi 11 Alexandria
 
#5

AW: (Formular-)Handling größerer Projekte

  Alt 11. Mär 2015, 12:41
Hi mm1256

Wenn du das Formular aus sich selber heraus schliessen willst, dann musst du es mit Release freigeben. Machst du das mit Free oder FreeAndNil, wird das Formular freigegeben, und die Ausführung kehrt zur auslösenden Prozedur zurück - die nicht mehr da ist, da das Formular freigegeben wurde. Und desshalb knallts.
Wenn du hingegen von einem MDI-Fenster ein MDI-Childd freigibst (zB.), passiert das nicht.

Gruss
Delbor
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch

Geändert von Delbor (11. Mär 2015 um 12:46 Uhr)
  Mit Zitat antworten Zitat
mm1256

Registriert seit: 10. Feb 2014
Ort: Wackersdorf, Bayern
642 Beiträge
 
Delphi 10.1 Berlin Professional
 
#6

AW: (Formular-)Handling größerer Projekte

  Alt 11. Mär 2015, 12:45
Danke für den Tipp. Hab es soeben mal ausprobiert. Funktioniert.

Ein Verständnisproblem (ich möchte ja auch verstehen was ich mache und nicht nur irgend einen Code abschreiben ) hab ich noch: Wenn ich im "OnClose" mit FrmClient1:=nil die Variable FrmClient1 auf NIL setze, wie schafft es Delphi (der Speichermanager oder was auch immer...) dann hinterher die Variable FrmClient1 trotzdem noch frei zu geben?
Gruss Otto PS: Sorry wenn ich manchmal banale Fragen stelle. Ich bin Hobby-Programmierer und nicht zu faul die SuFu zu benutzen
  Mit Zitat antworten Zitat
mm1256

Registriert seit: 10. Feb 2014
Ort: Wackersdorf, Bayern
642 Beiträge
 
Delphi 10.1 Berlin Professional
 
#7

AW: (Formular-)Handling größerer Projekte

  Alt 11. Mär 2015, 12:49
@Delbor Sorry, hat sich jetzt überschnitten.

Die Verwendung von Release bei modalen Fenstern ist mir klar. Aber bei normalen und MDI-Fenstern verstehe ich das noch nicht ganz. So wie es aussieht scheint aber die von "bcvs" vorgeschlagene Variante zu funktionieren.
Gruss Otto PS: Sorry wenn ich manchmal banale Fragen stelle. Ich bin Hobby-Programmierer und nicht zu faul die SuFu zu benutzen
  Mit Zitat antworten Zitat
bcvs

Registriert seit: 16. Jun 2011
703 Beiträge
 
Delphi 12 Athens
 
#8

AW: (Formular-)Handling größerer Projekte

  Alt 11. Mär 2015, 12:56
Du erzeugst ja eine Instanz der Klasse TForm. Diese Diese Instanz gibt sich selbst frei, wenn im das Action im Onclose auf caFree steht. Dazu braucht es eigentlich überhapt keine Instanzvariable (in deinem Fall FrmClient1).

Dein FrmClient zeigt nur zusätzlich noch auf die Instanz, kann aber auch nil sein oder theoretisch sonst irgendwohin zeigen.
  Mit Zitat antworten Zitat
mm1256

Registriert seit: 10. Feb 2014
Ort: Wackersdorf, Bayern
642 Beiträge
 
Delphi 10.1 Berlin Professional
 
#9

AW: (Formular-)Handling größerer Projekte

  Alt 11. Mär 2015, 13:08
Jetzt ist mir das auch klar. "zusätzlich" war das magische Wort. Vielen Dank nochmals für deine Hilfe!
Gruss Otto PS: Sorry wenn ich manchmal banale Fragen stelle. Ich bin Hobby-Programmierer und nicht zu faul die SuFu zu benutzen
  Mit Zitat antworten Zitat
Delbor

Registriert seit: 8. Okt 2006
Ort: St.Gallen/Schweiz
1.186 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: (Formular-)Handling größerer Projekte

  Alt 12. Mär 2015, 10:41
Hi zusammen

Diese Diese Instanz gibt sich selbst frei, wenn im das Action im Onclose auf caFree steht.
Das stimmt so nicht. Der Parameter Action steuert lediglich, was geschehen soll. Wird ihm caFree zugewiesen, wird das Formular tatsächlich geschlossen
Nach wie vor: ein Formular, das sich selbst freigeben soll, muss mit Release geschlossen werden.
Ein Beispiel:
Delphi-Quellcode:
var TForm1;

implementation;

...
...

procedure TForm1.ButtonClose.Onclick(Sender:TObject);
begin
Form1.Close;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
Action:= caFree;
//Action := caHide;
end;
Hier klickt der Anwender auf den Button, der sich in Form1 befindet. Dadurch wird OnClose aufgerufen; die Programmausführung arbeitet also FormOnClose ab und tut das, was der Parameter Action vorsieht. In diesem Fall wird das Formular freigegeben (es könnte auch nur versteckt (etc) werden).
Nachdem FormClose abgearbeitet ist, kehrt die Programmmausführung zur aufrufenden Prozedur zurück - aber Scheibenkleister, die ist ja gar nicht mehr da!! Also was macht Delphi! Eine AV auslösen?

Mit Form1.Release kann dies verhindert werden.
Hier solltest du dir die Warnung zu Herzen nehmen

Ein modales Formular kann, muss aber nicht mit Release freigegeben werden, da sich die Behandlungsroutine nicht im modalen Formular befindet.

Gruss
Delbor
Roger
Man muss und kann nicht alles wissen - man muss nur wissen, wo es steht.
Frei nach Albert Einstein
http://roase.ch

Geändert von Delbor (12. Mär 2015 um 10:47 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 4  1 23     Letzte »    


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 22:00 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