![]() |
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:
Aber OnDestroy bereitet mir noch Probleme.
procedure TMyComp.Loaded;
begin inherited; if Assigned(FOnCreate) then begin FOnCreate(self); end; 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? |
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. |
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. |
AW: Eigene Komponente mit OnClose-Event
Danke himitsu.
Dann bin ich also doch nicht zu blöd, etwas entsprechendes zu finden. :-D |
AW: Eigene Komponente mit OnClose-Event
Man kann durchaus in so einem
Delphi-Quellcode:
Event mit ShowMessage arbeiten ... wenn man etwas beachtet:
OnDestroy
Delphi-Quellcode:
procedure TFooForm.MyComponentDestroy( Sender: TObject );
begin if not csDestroying in Application.ComponentState then ShowMessage( 'Bin dann mal weg!' ); end; |
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. |
AW: Eigene Komponente mit OnClose-Event
Zitat:
|
AW: Eigene Komponente mit OnClose-Event
Das mache ich ja jetzt auch:
Delphi-Quellcode:
In der Form sieht es dann so aus:
procedure TMyComp.BeforeDestruction;
begin if Assigned(FOnDestroy) then begin FOnDestroy(Self); end; inherited; end;
Delphi-Quellcode:
Das ShowMessage wird zwar durchlaufen, aber nicht ausgeführt.
procedure TfrmMain.MyCompDestroy(Sender: TObject);
begin ShowMessage('Meine Komponente OnDestroy'); end; 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. |
AW: Eigene Komponente mit OnClose-Event
Also ich weiß nicht, was da nicht funtionieren sollte, denn das funktioniert hier einwandfrei:
Die Komponente
Delphi-Quellcode:
und die Form
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.
Delphi-Quellcode:
Solange die Anwendung selber nicht beendet wird, erscheint immer die Message.
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. |
AW: Eigene Komponente mit OnClose-Event
Zitat:
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:
Also ist nur das Handle der MainForm ungültig. Das Handle der Anwendung ist aber noch nutzbar.
MessageBox(Application.Handle, 'Komponente OnDestroy', 'TMyComp', 0);
|
AW: Eigene Komponente mit OnClose-Event
Zitat:
Es gibt hier nur eine Regel, die man beachten muss
Delphi-Quellcode:
oder auf deutsch:
if not( csDestroying in Application.ComponentState ) then
ShowMessage( 'Ich bin dann mal weg!' ); Wenn die Anwendung selber den Status Zerstören hat, dann darf ich bestimmte Dinge nicht mehr machen (wie. z.B.
Delphi-Quellcode:
aufrufen).
ShowMessage
|
AW: Eigene Komponente mit OnClose-Event
ShowMessage wird hier wohl über CreateDialogIndirect erstellt und das reagiert auf Application.Terminated und schießt sich sofort wieder, da es so eine VCL-TForm ist.
(altes Delphi oder altes Windows) |
AW: Eigene Komponente mit OnClose-Event
@Sir Rufo, das ist mir schon klar. Ich bin halt davon ausgegangen, dass das BeforeDestruction ausgeführt, bevor irgendwas anderes tatsächlich zerstört wird. Dies ist aber offensichtlich eine falsche Annahme gewesen. Asche auf mein Haupt.
Als Nutzer einer Komponente würde es mich allerdings schon irritieren, dass ich erst prüfen muss, ob ich in der Anwendung überhaupt ein ShowMessage aufrufen darf, wenn das gewünschte Ereignis abgearbeitet wird. @himitsu: Es macht zumindest den Eindruck, dass es so abläuft. |
AW: Eigene Komponente mit OnClose-Event
Zitat:
Zitat:
|
AW: Eigene Komponente mit OnClose-Event
@Jasocul
Was glaubst du wohl, wieviele Nutzer von Kettensägen überrascht geschaut haben, als sie den Ast abgesägt haben auf dem sie selber gerade saßen? Egal was man hat (Kettensäge, Komponente, ...): Man kann es richtig oder falsch verwenden. Und das oben geschilderte Verhalten ist kein Alleinstellungsmerkmal der Kettensäge. |
AW: Eigene Komponente mit OnClose-Event
@Mikkey:
Ja, ich weiß das. Aber die Kollegen, die die Komponente nutzen, sehen ja nur, dass es ein Event gibt, das sie benutzen können. Was dahinter steckt, ist erstmal uninteressant. Wenn ich in so einem Event eine Nachricht ausgeben möchte, sollte das auch passieren. @Sir Rufo: Natürlich muss man aufpassen, dass das, was man benutzt, auch da ist. Aber bisher war es bei mir bisher nicht erforderlich, dass ich prüfen muss, ob die Anwendung noch "existiert", in der ich den Code ablaufen lasse. |
AW: Eigene Komponente mit OnClose-Event
Zitat:
Deine Komponente stellt doch nur sicher, dass der Event zum angegeben Zeitpunkt aufgerufen wird - Punkt. Und das macht die doch auch. Was willst du also noch? Im Übrigen habe ich festgestellt, dass auch der Befehl
Delphi-Quellcode:
nicht korrekt ausgeführt wird.
ÜbernehmeDieWeltherrschaft();
Es liegt nicht in der Verantwortlichkeit der Komponente, ob der Eventhandler-Code korrekt abgearbeitet wird, sondern ausschließlich darin, dass der Event aufgerufen wird, wie vereinbart. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:37 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