Entwickler-Ecke

Sonstiges (Delphi) - Programm beenden endet in Zugriffsverletzung.


Danny87 - Mi 15.02.06 15:08
Titel: Programm beenden endet in Zugriffsverletzung.
ich möchte mein prog folgendermaßen beenden:


Die Zugriffsverletzung - frmNavigator.btnBeendenClick
1:
2:
3:
4:
5:
6:
procedure TfrmNavigator.btnBeendenClick(Sender: TObject);
begin
if Assigned(frmNeuesProdukt) then
  frmNeuesProdukt.Close;
frmMain.Close;
end// Ab hier Zugriffsverletzung


Im OnClose von frmMain steht das:
1:
2:
3:
4:
5:
6:
7:
8:
procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if assigned(frmNavigator) then
  FreeAndNil(frmNavigator);

if assigned(frmNeuesProdukt) then
  FreeAndNil(frmNeuesProdukt);
end;


frmNavigator und frmNeuesProdukt sind MDI-Children,
frmMain ist die MDI-Form.

Wenn ich das so mache bekomme, ich allerdings eine Zugriffsverletzung an Adresse blablabla.
Warum?
Und:
Wie kann ich das umgehen?

gruss daniel


jasocul - Mi 15.02.06 15:22

Meine Routine:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  // Folgende Routine ist erforderlich, da es sonst zu einer Zugriffsverletzung kommt, wenn noch
  // MDI-Child-Fenster geöffnet sind.
  while MDIChildCount > 0 do
  begin
    if TForm(MDIChildren[MDIChildCount - 1]).Owner = self then
    begin
      TForm(MDIChildren[MDIChildCount - 1]).Close;
    end;
    Application.ProcessMessages;
  end;
end;

Wie du am Source-Kommentar siehst, ist es ein bekanntes Phänomen.


Danny87 - Mi 15.02.06 15:35

hmm... mit deiner routine passiert bei mir nix... :gruebel:

es sieht allerdings so aus, als sei es eine endlosschleife. beenden geht auch nicht mehr über das [x] in der titelleiste,
geschweige denn übers MainMenu.
vorher hat das funktioniert.

Ich hab das

Delphi-Quelltext
1:
2:
3:
if Assigned(frmNeuesProdukt) then
  frmNeuesProdukt.Close;
frmMain.Close;

übrigens auch im MainMenu drinstehen:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
procedure TfrmMain.miBeendenClick(Sender: TObject);
begin
if Assigned(frmNeuesProdukt) then
  frmNeuesProdukt.Close;
frmMain.Close;
end;

und da funktionierts.


jasocul - Mi 15.02.06 15:40

Das ist merkwürdig. Die Routine läuft bei mir seit einigen Jahren. Eine Endlosschleife kann es nur werden, wenn sich die Anzahl der MDI-Childs nicht bis auf 0 reduziert.
Hast du in den Close oder CloseQuery-Methoden noch was drin? Eventuell wird dadurch das Schließen verhindert.
Gehe die Routine doch mal mit dem Debugger durch und schau dir den Wert an.


Danny87 - Mi 15.02.06 15:44

hab ich grad getan.
grund der endlosschleife:


Delphi-Quelltext
1:
2:
3:
4:
if TfrmMain(MDIChildren[MDIChildCount - 1]).Owner = self then // Owner ist nie self
  begin
    TfrmMain(MDIChildren[MDIChildCount - 1]).Close;
  end;


verstehen tu ichs auch nicht...


jasocul - Mi 15.02.06 15:49

wie erzeugst du denn die Childs? Mit Application.CreateForm?
Ich mache es im Prinzip so:

Delphi-Quelltext
1:
2:
3:
4:
procedure TfrmMain.mnuNeuesProduktClick(Sender: TObject);
begin
  frmNeuesProdukt := TfrmNeuesProdukt.Create(Self);
end;

Dadurch ist die MDI-Form (frmMain) der Owner der Childs.


Danny87 - Mi 15.02.06 15:57

habs jetzt mit create(self) gemacht. funktioniert aber immer noch nicht. der MDIChildCount ist immer = 1, weil
das MDIChild immer nur minimiert wird (mit Close;).

Muss man da nicht FreeAndNil oder so was machen?


Danny87 - Mi 15.02.06 16:01

ich habs!! es geht jetzt!
Ich hab ins OnClose von frmNavigator folgendes reingeschrieben:

Delphi-Quelltext
1:
2:
if Assigned(frmNavigator) then
  FreeAndNil(frmNavigator);



Danke für die Hilfe!


gruss daniel