Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Delphi Eigene Komponente mit OnClose-Event (https://www.delphipraxis.net/185331-eigene-komponente-mit-onclose-event.html)

Jasocul 1. Jun 2015 08:18

Eigene Komponente mit OnClose-Event
 
Ich stehe gerade auf dem Schlauch oder habe ein Brett vor dem Kopf. ganz wie ihr wollt.
Ich habe eine Komponente programmiert, die jetzt ein OnCreate- und ein OnDestroy-Ereignis bekommen soll.

Die Komponente ist abgeleitet von TComponent.
Das OnCreate funktioniert inzwischen, nachdem ich den üblichen Standard-Source in die protected Methode Loaded eingebaut (AfterConstruction war zu früh) habe:
Delphi-Quellcode:
procedure TMyComp.Loaded;
begin
  inherited;

  if Assigned(FOnCreate) then
  begin
    FOnCreate(self);
  end;
Aber OnDestroy bereitet mir noch Probleme.
BeforeDestruction ist zu spät.
Mache ich es mit Message-Handling, ist die Applikation offensichtlich schon nicht mehr verfügbar. Zumindest habe ich keinen Zugriff mehr. Ein einfaches ShowMessage wird schon nicht mehr angezeigt, obwohl fehlerfrei durch den Source gelaufen wird (Debugger).

Google spuckt auch nichts Brauchbares aus (oder ich stelle die falsche Frage).

Weiß jemand, wie es richtig geht und kann mir das verraten?

Jasocul 1. Jun 2015 10:39

AW: Eigene Komponente mit OnClose-Event
 
Ich habe es jetzt erstmal im BeforeDestruction eingebaut.
Damit sollte die Komponente zumindest die zur Zeit geplanten Routinen im OnDestroy abarbeiten können. Anwender-Benachrichtigungen mit ShowMessage gehen so allerdings leider nicht.

himitsu 1. Jun 2015 11:12

AW: Eigene Komponente mit OnClose-Event
 
Bei einer Komponente ist BeforeDestruction das Früheste, was es gibt.
Ausnahme, wenn z.B. in der Form ein Code eingebaut wurde, welcher die Komponente rechtzeitig informiert. (leider gibt es kein TComponent.BeforeClose, zu dem TComponent.Loaded und TObject.BeforeDestruction)

Bei Forms gibt es noch OnCloseQuery und OnClose, aber das wird natürlich nicht aufgerufen, wenn im Programm Form.Free azfgerufen wird, sondern nur beim Form.Close.

Jasocul 1. Jun 2015 11:17

AW: Eigene Komponente mit OnClose-Event
 
Danke himitsu.
Dann bin ich also doch nicht zu blöd, etwas entsprechendes zu finden. :-D

Sir Rufo 1. Jun 2015 11:24

AW: Eigene Komponente mit OnClose-Event
 
Man kann durchaus in so einem
Delphi-Quellcode:
OnDestroy
Event mit ShowMessage arbeiten ... wenn man etwas beachtet:
Delphi-Quellcode:
procedure TFooForm.MyComponentDestroy( Sender: TObject );
begin
  if not csDestroying in Application.ComponentState then
    ShowMessage( 'Bin dann mal weg!' );
end;

Jasocul 1. Jun 2015 11:45

AW: Eigene Komponente mit OnClose-Event
 
Nette Idee, funktioniert aber nicht. Ich habe es vorsichtshalber auch nochmal getestet. ShowMessage wird auf keinen Fall ausgeführt. :wink:

Eigentlich ist das Verhalten auch korrekt. Wenn die Form zerstört wird, bekommen alle Komponenten, deren Owner die Form ist, die Nachricht, sich zu zerstören. Wenn eine Komponente jetzt im eigenen Destroy einen Event-Handler bekommt, kann es zu merkwürdigen Nebeneffekten kommen. Allein der Zugriff auf andere Komponenten, die auf der Form liegen, kann zu unkontrollierbaren Zugriffsverletzungen führen. Klar kann man die Erstellungsfolge beeinflussen, aber eine Komponente sollte schon richtig gekapselt sein.
Dieses Problem kann mich natürlich auch im BeforeDestruction treffen, aber es handelt sich um eine firmeninterne Komponente, die dann entsprechend dokumentiert ist.

Das, was die Komponente in dem Ereignis machen soll, funktioniert problemlos. Nur eine Rückmeldung an den Anwender müssen wir gegebenenfalls anders lösen. Normalerweise ist die Rückmeldung aber nicht erforderlich.

himitsu 1. Jun 2015 11:51

AW: Eigene Komponente mit OnClose-Event
 
Zitat:

kann es zu merkwürdigen Nebeneffekten kommen.
Darum muß der auch im BeforeDestruction aufgerufen werden, denn die Form sendet erst an alle Komponenten das BeforeDestruction und danach nacheinander Free/Destroy aufgerufen.

Jasocul 1. Jun 2015 12:01

AW: Eigene Komponente mit OnClose-Event
 
Das mache ich ja jetzt auch:
Delphi-Quellcode:
procedure TMyComp.BeforeDestruction;
begin
  if Assigned(FOnDestroy) then
  begin
    FOnDestroy(Self);
  end;

  inherited;
end;
In der Form sieht es dann so aus:
Delphi-Quellcode:
procedure TfrmMain.MyCompDestroy(Sender: TObject);
begin
  ShowMessage('Meine Komponente OnDestroy');
end;
Das ShowMessage wird zwar durchlaufen, aber nicht ausgeführt.
Wenn ich die Variante von Sir Rufo verwende, ist die Bedingung im If nicht erfüllt. Dementsprechend ist das Verhalten dann identisch, bis auf die zusätzliche Prüfung.

Sir Rufo 1. Jun 2015 12:06

AW: Eigene Komponente mit OnClose-Event
 
Also ich weiß nicht, was da nicht funtionieren sollte, denn das funktioniert hier einwandfrei:

Die Komponente
Delphi-Quellcode:
unit MyComponent;

interface

uses
  System.Classes;

type
  TMyComponent = class( TComponent )
  private
    FOnDestroy: TNotifyEvent;
  protected
    procedure NotifyOnDestroy;
  public
    procedure BeforeDestruction; override;
  published
    property OnDestroy: TNotifyEvent read FOnDestroy write FOnDestroy;
  end;

implementation

{ TMyComponent }

procedure TMyComponent.BeforeDestruction;
begin
  NotifyOnDestroy( );
  inherited;

end;

procedure TMyComponent.NotifyOnDestroy;
begin
  if Assigned( FOnDestroy ) then
    FOnDestroy( Self );
end;

end.
und die Form
Delphi-Quellcode:
unit Unit2;

interface

uses
  MyComponent,

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

type
  TForm2 = class( TForm )
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate( Sender: TObject );
    procedure Button1Click( Sender: TObject );
    procedure Button2Click( Sender: TObject );
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    FMyComponent: TMyComponent;
    procedure CreateMyComponent;
    procedure MyComponentDestroy( Sender: TObject );
  public
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.Button1Click( Sender: TObject );
begin
  FreeAndNil( FMyComponent );
end;

procedure TForm2.Button2Click( Sender: TObject );
begin
  CreateMyComponent( );
end;

procedure TForm2.CreateMyComponent;
begin
  FreeAndNil( FMyComponent );
  FMyComponent := TMyComponent.Create( Self );
  FMyComponent.OnDestroy := MyComponentDestroy;
end;

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

procedure TForm2.FormCreate( Sender: TObject );
begin
  CreateMyComponent( );
end;

procedure TForm2.MyComponentDestroy( Sender: TObject );
begin
  if not( csDestroying in Application.ComponentState ) then
    ShowMessage( 'Ich bin dann mal weg!' );
end;

end.
Solange die Anwendung selber nicht beendet wird, erscheint immer die Message.

Jasocul 1. Jun 2015 12:12

AW: Eigene Komponente mit OnClose-Event
 
Zitat:

Zitat von Sir Rufo (Beitrag 1303782)
Solange die Anwendung selber nicht beendet wird, erscheint immer die Message.

Ah, da ist unser Missverständnis. Ich erzeuge die Instanz nicht zur Laufzeit. Dementsprechend zerstöre ich diese auch nicht selbst.
Die MainForm der Anwendung wird geschlossen und somit auch die Anwendung. Das Handle der MainForm ist dann im Event schon nicht mehr verfügbar.
Was allerdings funktioniert ist folgendes:
Delphi-Quellcode:
MessageBox(Application.Handle, 'Komponente OnDestroy', 'TMyComp', 0);
Also ist nur das Handle der MainForm ungültig. Das Handle der Anwendung ist aber noch nutzbar.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:05 Uhr.
Seite 1 von 2  1 2      

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