Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Delphi FormCloseQuery FormShowing abfrage (https://www.delphipraxis.net/158610-formclosequery-formshowing-abfrage.html)

Capa 23. Feb 2011 19:29

FormCloseQuery FormShowing abfrage
 
Also immo sieht mein Code so aus
der soll quasi abfragen ob noch eine Form offen ist und wenn nicht schliessen
ansonsten fehlermeldung.
Soweit so gut nun hab ich das Problem das ständig neue Forms dazu kommen da
dachte ich mir muss das ganze etwas vereinfachen und hab eine version geschrieben
wo ich nur nen integer wert ändern muss.
nun funzt das aber nicht so wirklich.

Alte Version:
Delphi-Quellcode:
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  CanClose := False;
  if (not Form2.Showing) then
    if (not Form3.Showing) then
      if (not Form4.Showing) then
        if (not Form5.Showing) then
          if (not Form6.Showing) then
           if (not Form7.Showing) then
            CanClose := True;

  if (not CanClose) then
    MessageDlg('Bitte erst alle Fenster schließen bevor das Hauptfenster geschlossen wird!', mtError, [mbOK], 0);
end;
Neue Version:
Delphi-Quellcode:
var maxfom: integer;

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
var i,L: integer;
begin
  CanClose := False;
  L := 1;
  for i := 2 to maxform do  // fängt mit 2 an weil Form1 ja nicht abgefragt werden soll.
  begin
    if (not TForm('Form'+inttostr(i)).Showing) then
      L := L + 1
  end;

  if (L = maxform) then
    Canclose := True;

  if (not CanClose) then
    MessageDlg('Bitte erst alle Fenster schließen bevor das Hauptfenster geschlossen wird!', mtError, [mbOK], 0);
end;
im OnCreate wird noch die aktuelle Anzahl der Forms gesetzt steht immo bei 8.

Das Problem ist das der nun auch das fenster schliesst wenn noch ne form offen ist, was ja damit normalerweile verhindert werden soll. Sieht jemand nen Fehler da drin den ich seh irgendwie keinen
is ja im endeffekt nix anderes als die obere version


An anderer Stelle hab ich folgenden Code:
Delphi-Quellcode:
  for i := 1 to maxform do
    TForm('Form'+inttostr(i)).Font := FontDialog1.Font;
nur bekomm ich da ne Zugriffsverletzung :/

"Zugriffsverletzung bei Adresse 004B2316 in Modul 'Project1.exe'. Lesen von Adresse 00000000"

MGC 23. Feb 2011 20:31

AW: FormCloseQuery FormShowing abfrage
 
Schließt Dein Programm nur wenn noch 1 Form offen ist (außer dem Hauptform) oder auch wenn noch mehr Forms geöffnet sind?
Du schreibst maxforms = 8, prüfst aber nur die Forms 2-7 (=6).
Ich würde auch die Abfrage nicht undbedingt hardcoded gestalten, da Du Dir dadurch nur zusätzliche Arbeit bei späteren Erweiterungen machst.

Capa 23. Feb 2011 20:39

AW: FormCloseQuery FormShowing abfrage
 
Es soll quasi nur dann schliessen wenn Form1 die einzige angezeigte form ist.

Zitat:

Du schreibst maxforms = 8, prüfst aber nur die Forms 2-7 (=6).
? wieso das
Delphi-Quellcode:
for i := 2 to maxform do
der fängt mit Form2 an und hört mit Form8 auf hab da ja kein maxform-1 stehen
form 1 is ja klar das die noch angezeigt wird weils das hauptfenster ist, aber
alle anderen sollen geschlossen werden.

Delphi-Quellcode:
L := 1;
und das was ich bei der for schleife mit 2 anfange hab ich vorher ja schon festgelegt bei L

Christian Seehase 23. Feb 2011 20:43

AW: FormCloseQuery FormShowing abfrage
 
Moin Capa,

hier mal ein anderer Ansatz:


Delphi-Quellcode:
var
  i : Integer;

begin
  for i := 0 to Application.ComponentCount-1 do begin
    if Application.Components[i] is TForm then begin
      if (Application.Components[i] as TForm).Visible and
         ((Application.Components[i] as TForm).Tag = 1) then begin
        CanClose := False;
        break;
      end;;
    end;
  end;
  if not CanClose then MessageBox(self.Handle,'Erst alle anderen Formulare schliessen','Fehler',MB_ICONERROR);
end;
Alle Unterformulare bekommen, entweder manuell im Objektinspektor, oder per Programm im OnCreate die Eigenschaft Tag auf 1 gesetzt (Tag ist ein beliebig verwendbarer Integerwert).
Sobald eines sichbar ist, und Tag=1 ist darf das Hauptformular nicht geschlossen werden.

Capa 23. Feb 2011 20:53

AW: FormCloseQuery FormShowing abfrage
 
funzt super :) danke
dann weiß ich jetzt auch wie ich meine anderen Probleme lösen kann ;)

Mfg Capa

Sir Rufo 24. Feb 2011 01:56

AW: FormCloseQuery FormShowing abfrage
 
Wofür denn das Tag setzen? Nur um herauszufinden, ob die Form nicht die MainForm ist?

Delphi-Quellcode:
If MyForm <> Application.MainForm then
Das geht immer und man kann dabei nichts vergessen (z.B. das Tag setzen)

Capa 24. Feb 2011 11:23

AW: FormCloseQuery FormShowing abfrage
 
Wenns mir um die Mainform gehen würde könnte ich auch name='Form1'; abfragen
aber so kann ich zum bsp auch das Programm schliessen lassen, wenn noch ne Form angezeigt wird
wo keine speicherrelevanten daten drin sind sondern nur anzeigen.

DeddyH 24. Feb 2011 12:18

AW: FormCloseQuery FormShowing abfrage
 
Könnte man nicht einfach Screen.FormCount abfragen?

Sir Rufo 24. Feb 2011 14:55

AW: FormCloseQuery FormShowing abfrage
 
Diese MainForm prüft alle (mit Application als Owner) Formulare, ob diese sich schließen können.

Mit der Property CloseForce kann man das Schliessen erzwingen (was beim Abmelden/Herunterfahren -> WM_ENDSESSION auch gemacht wird).
Delphi-Quellcode:
unit frmMain;

interface

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

type
  TForm1 = class( TForm )
    procedure FormCloseQuery( Sender : TObject; var CanClose : Boolean );
    procedure FormCreate( Sender : TObject );
  private
    FCloseForce : Boolean;
  protected
    procedure WMEndSession( var message : TWMEndSession ); message WM_ENDSESSION;
  public
    property CloseForce : Boolean
      read  FCloseForce
      write FCloseForce;
  end;

var
  Form1 : TForm1;

implementation

uses
  frmData;

{$R *.dfm}

procedure TForm1.FormCloseQuery( Sender : TObject; var CanClose : Boolean );
var
  idx : Integer;
begin
  if not CloseForce
  then
    for idx := 0 to Application.ComponentCount - 1 do
      if ( Application.Components[idx] <> Self ) and ( Application.Components[idx] is TForm )
      then
        CanClose := CanClose and TForm( Application.Components[idx] ).CloseQuery;
end;

procedure TForm1.FormCreate( Sender : TObject );
begin
  CloseForce := False;
end;

procedure TForm1.WMEndSession( var message : TWMEndSession );
begin
  inherited;
  CloseForce := True;
end;

end.

Capa 24. Feb 2011 16:15

AW: FormCloseQuery FormShowing abfrage
 
oO wieso sollte ich das den erzwingen wollen der user soll doch das programm solange nicht schliessen können
bis alle forms geschlossen sind, wenn ich das nun erzwinge is doch das ganze was ich damit versuche zu erreichen
zwecklos oder seh ich das falsch ?

Sir Rufo 24. Feb 2011 16:19

AW: FormCloseQuery FormShowing abfrage
 
Zitat:

Zitat von Capa (Beitrag 1084178)
oO wieso sollte ich das den erzwingen wollen der user soll doch das programm solange nicht schliessen können
bis alle forms geschlossen sind, wenn ich das nun erzwinge is doch das ganze was ich damit versuche zu erreichen
zwecklos oder seh ich das falsch ?

Du kannst, musst aber nicht.

Wird der Rechner heruntergefahren, dann blockiert das Programm dieses nicht!

MGC 24. Feb 2011 22:47

AW: FormCloseQuery FormShowing abfrage
 
Also, mir gefällt Sir Rufos Ansatz sehr gut. Wieso sollte man auch den User damit beschäftigen jedes untergeordnete Form händisch zu schließen anstatt dies zu automatisieren und über deren Form.CloseQuery die Möglichkeit zum Speichern der Daten anzubieten.
Du, kannst ja das CloseForce noch ein wenig erweitern und eine Zeitspanne vorgeben innerhalb der ein User die Daten noch speichern kann, bevor das Schließen beim Herunterfahren erzwungen wird.
Regelmäßige User werden sich für diese Automation bedanken und das egal ob sie dei MainForm schließen oder einfach den Rechner herunterfahren.

Capa 25. Feb 2011 13:44

AW: FormCloseQuery FormShowing abfrage
 
die frage ist dann allerdings kann ich überhaupt noch speichern wenn der rechner runtergefahren wird und ich das quasi anhalte. Den das ganze ist eine DB-Anwendung und wenn ich pech hab und der mir die netzwerkverbindung killt dann kann der user auch nicht mehr speichern.
Im Normalfall soll der User ja auch das Programm beenden bevor er den rechner runterfährt.

MGC 25. Feb 2011 19:56

AW: FormCloseQuery FormShowing abfrage
 
Sehr gut, Problem gelöst. Nach Sir Rufos Vorschlag wird bei Programmende der FormCloseQiery jedes Child-Forms aufgerufen und der Anwender kann somit über das Fehlende Speichern informiert werden.
Beim herunterfahrern des Rechners sollte der Anwender also ohne seine Änderungen gespeichert haben und falls er "zu faul" ist seine Anwendung zu schließen bevor er den Rechner herunterfährt, wird einfach das Programm abgeschossen/forced, um den Vorgang des Hereunterfahrens nicht zu blockieren.
Noch eine entsprechende Bemerkung in die Bedienungsanleitung und fertig.

Capa 25. Feb 2011 20:04

AW: FormCloseQuery FormShowing abfrage
 
bedienungsanleitung hehe der war gut mein chef brauchs
so einfach wir möglich der hat garnicht die zeit ne
bedienungsanleitung zu lesen ^^
Da es hier um wichtige daten geht sollte der anwender
schon speichern können sonst gehen nicht gespeicherte
abrechnungsdaten, Kunden bzw Personaldaten, etc verloren
ist nicht ohne was da alles passieren kann wenn das programm
einfach so gekillt wird.

Ich hab sogar schon ne sichheit eingebaut das nicht einfach
was gelöscht werden kann, zumindest nicht für immer ^^
kann quasi jeden löschvorgang rückgängig machen.
Sollte mal jemand was aus versehen löschen wirds wieder hergestellt.

Mfg Capa

Sir Rufo 25. Feb 2011 20:53

AW: FormCloseQuery FormShowing abfrage
 
Wie du auf den Event reagierst bleibt dir überlassen.

Was man definitiv nicht machen sollte, beim Abmelden der Session (Abmelden/Herunterfahren) einen Dialog aufrufen "Wollen SIe speichern?".
Ist total blöde, wenn der User die Anwendung noch geöffnet hat und in der Nacht sollen Updates eingespielt werden.

Darum

Möglichkeit A: Schmeiß die nicht gesicherten Daten in die Tonne (der User ist halt selber schuld)

Möglichkeit B: Speicher die nicht gesicherten Daten in einer Sicherungs-Datei und beim nächsten Start der Anwendung werden die Formulare wieder mit diesen Daten erstellt und der Benutzer kann dann entscheiden, was damit passieren soll.

Capa 26. Feb 2011 11:55

AW: FormCloseQuery FormShowing abfrage
 
mhh wenn du das so sagst tendiere ich zu A den B is ja nen riesen aufwand
und ich wollt das programm noch dieses Jahr fertig bekommen ;)

Achja und Nachts sind unsere Computer alle aus.
Und wir hängen "Zum Glück" nicht am Intranet dran von daher werden auch keine
updates eingespielt :) wenn dann mach ich das noch von hand wenn ich vorm PC sitze.

MGC 26. Feb 2011 17:19

AW: FormCloseQuery FormShowing abfrage
 
Wozu dann überhaupt den ganzen Aufwand mit den FormCloseQueries, wenn Du am Ende doch nur die "Schmalspurvariante" wählst?
Wenn Du Deinen Chef im Verdacht hast, des öfteren mal einen "OSI Level 8"-Fehler zu produzieren, dann
schreib doch erstmal einen Prototyp für den Einstieg und rüste die temporäre Datenspeicherung in einer späteren Iteration nach.


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:40 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