Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi Problem mit Freigeben von CreateMessageDialog (https://www.delphipraxis.net/83778-problem-mit-freigeben-von-createmessagedialog.html)

Helmi 6. Jan 2007 11:16


Problem mit Freigeben von CreateMessageDialog
 
Hallo Jungs und Mädels,

ich erzeuge im OnCreate einer Form eine MessageForm mit CreateMessageDialog:

Delphi-Quellcode:
  //Meldungs-Form erzeugen und beschreiben
  MessageForm := CreateMessageDialog(Msg3, mtInformation, []);
  with MessageForm do
    begin
      BorderIcons := [];
      BorderStyle := bsNone;

      Font.Height := 15;
      Font.Style := [fsBold];
      Color      := $00F8E4D8;
      Height     := 55;
      Width      := 320;
      FormStyle  := fsStayOnTop;

      OnPaint    := OnPaintMessageForm;
    end;
die Variable MessageForm ist im private-Bereich als TForm deklariert.

Soweit so gut - es funktioniert bestens.

Nur, soviel ich weiss, muss man "alles" was man erzeugt auch wieder im OnDestroy der Form freigeben.
Also mach ich im OnDestroy der Form:
Delphi-Quellcode:
FreeAndNil(MessageForm);
Nur erhalte ich dabei folgende AccessViolation:

Zitat:

---------------------------
Benachrichtigung über Debugger-Exception
---------------------------
Im Projekt Project1.exe ist eine Exception der Klasse EAccessViolation aufgetreten. Meldung: 'Zugriffsverletzung bei Adresse 00000010. Lesen von Adresse 00000010'. Prozess wurde angehalten. Mit Einzelne Anweisung oder Start fortsetzen.
---------------------------
OK Hilfe
---------------------------
Nur warum?

Die Variable existiert - wird createt und müsste doch ganz einfach freizugeben sein, oder irre ich da mich?
Oder sind CreateMessageDialogs spezielle Forms?

Popov 6. Jan 2007 12:52

Re: Problem mit Freigeben von CreateMessageDialog
 
So, ich hab mir nochmal die Funktion in der Hilfe angeguckt und kann dir jetzt die Antwort auf deine Frage geben:

Delphi-Quellcode:
function CreateMessageDialog(const Msg: string; DlgType: TMsgDlgType; Buttons: TMsgDlgButtons): TForm;
Wie du siehst ist das Ergebnis von Typ TForm. Letztendlich ist es nur ein Zeiger den du bekommst, d.h. du erstellst keine Formular, das macht CreateMessageDialog für dich, du erhälst nur den Zeiger auf den Formular. Das ist nichts anderes wie eine Integer Variable. Um das Freigeben kümmert sich in diesem Fall Delphi selbst.

SirThornberry 6. Jan 2007 13:38

Re: Problem mit Freigeben von CreateMessageDialog
 
@Popov: Die Aussage ist schlichtweg falsch. Ein Constructor gibt auch nichts anderes zurück als einen Zeiger auf die Instanzdaten. Trotzdem sollte man wie der Fragesteller bereits erwähnt hat alles wieder freigeben was man vorher selbst erstellt hat.
Die Accessviolation deutet übrigens darauf hinn das zu diesem Zeitpunkt die Instanzvariable bereits auf nil gesetzt wurde. Rufst du eventuell vorher schonmal FreeAndNil oder ähnliches auf?

Helmi 6. Jan 2007 13:49

Re: Problem mit Freigeben von CreateMessageDialog
 
Hallo Sir Thornberry,

ich setz die Variable "MessageForm" zwischendurch nicht auf nil.

Auch wenn ich den o. s. Code rauslöse aus dem Projekt und in einem Test-Projekt allein laufen lasse (also nur erzeugen in OnCreate und in einem Button z. B. mit MessageForm.Show anzeigen lassen), passiert das gleiche im OnDestroy mit FreeAndNil(MessageForm).

SirThornberry 6. Jan 2007 13:51

Re: Problem mit Freigeben von CreateMessageDialog
 
ich würde das ganze nicht im OnDestroy plazieren sondern direkt hinter dem ShowModal. Denn genau dort wird der MessageDialog nicht mehr benötigt. Kommt dann auch der Fehler wenn du genau dort das ganze schon wieder freigibst?

Luckie 6. Jan 2007 14:00

Re: Problem mit Freigeben von CreateMessageDialog
 
Geht.
Delphi-Quellcode:
type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
    MessageForm: TForm;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  MessageForm.ShowModal;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  MessageForm := CreateMessageDialog('Test', mtInformation, []);
  with MessageForm do
    begin
      BorderIcons := [];
      BorderStyle := bsDialog;
      Font.Height := 15;
      Font.Style := [fsBold];
      Color      := $00F8E4D8;
      Height     := 55;
      Width      := 320;
      FormStyle  := fsStayOnTop;
    end;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  FreeAndNil(MessageForm);
end;

Helmi 6. Jan 2007 14:02

Re: Problem mit Freigeben von CreateMessageDialog
 
Hallo Sir,

ich kann es dort leider nicht hinsetzen, da ich die MessageForm nur mit Show/Hide anzeige bzw. verstecke weil ich es mehrmals anzeige bzw auch wieder verstecke.

Deswegen wird es im OnCreate auch einmal verwendet und dann nur immer mit show und hide angezeigt/versteckt

Hawkeye219 6. Jan 2007 14:27

Re: Problem mit Freigeben von CreateMessageDialog
 
Hallo Helmi,

wenn du in deine MessageForm einen Handler für das Ereignis OnDestroy einhängst, wirst du feststellen, daß der Dialog bereits freigegeben wurde, bevor dein Hauptformular zerstört wird. Deine lokale Variable MessageForm zeigt danach also auf ein bereits ungültiges Objekt.
Entweder verzichtest du auf die (überflüssige) Freigabe, oder du gibst das Formular - wie von Michael vorgeschlagen - im OnClose frei, oder du löschst im OnDestroy-Handler der MessageForm deine lokale Referenz.

Gruß Hawkeye

Popov 8. Jan 2007 20:28

Re: Problem mit Freigeben von CreateMessageDialog
 
@SirThornberry

Da muß ich dir leider Recht geben. Hab gerade deswegen noch die Enterprise installiert um an den Quellcode der Funktion zu kommen. Tatsächlich wird Create auf Result ausgeführt. Wie es aussieht habe ich es mit einer anderen Funktion verwechselt die mit den Parametern lediglich Änderung der Eigenschaften vornimmt, sonst aber nichts erstellt. Die hatte auch Create im Namen. Wie auch immer, Tests haben gezeigt, daß jeder Aufruf der Funktion neuen Speicher verbraucht.


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