Frage

Wie kann ich simulieren ein OnDestroy Ereignis für eine TFrame in Delphi?


i nievely eine constructor und destructor meinem Rahmen hinzugefügt, denken, dass ist das, was TForm tut:

TframeEditCustomer = class(TFrame)
...
public
   constructor Create(AOwner: TComponent); override;
   destructor Destroy; override;
   ...
end;

constructor TframeEditCustomer.Create(AOwner: TComponent)
begin
    inherited Create(AOwner);

    //allocate stuff
end;

destructor TframeEditCustomer.Destroy;
begin
   //cleanup stuff

   inherited Destroy;
end;

Das Problem dabei ist, dass durch die Zeit, mein destructor läuft, Kontrollen auf dem Rahmen zerstört wurden und nicht mehr gültig ist.

Der Grund hierfür ist in der Destruktor enthält Form, die es verwendet ein OnDestroy Ereignis ausgelöst:

destructor TCustomForm.Destroy;
begin
   ...
   if OldCreateOrder then DoDestroy; //-->fires Form's OnDestroy event; while controls are still valid
   ...
   if HandleAllocated then DestroyWindowHandle; //-->destroys all controls on the form, and child frames
   ...
   inherited Destroy; //--> calls destructor of my frame
   ...
end;

Der destructor meines Frame-Objekt aufgerufen wird, wenn die Destruktor der Form ausgeführt wird. Problem dabei ist, dass es zu spät ist. Die Form Anrufe DestroyWindowHandle, die von Windows fragt die Form des Fenstergriff zu zerstören. Dies zerstört rekursiv alle untergeordneten Fenster -. Einschließlich derjenigen auf meinem Rahmen

Also, wenn meine Rahmens destructor läuft, ich versuche, Zugriffskontrollen, die nicht mehr in einem gültigen Zustand.


Wie kann ich simulieren ein OnDestroy Ereignis für eine TFrame in Delphi?

Siehe auch

War es hilfreich?

Lösung

Sie benötigen einen WM_DESTROY Handler hinzuzufügen und für csDestroying im Component zu überprüfen, so dass es nur gefangen, wenn sie tatsächlich zu zerstören, und nicht, wenn der Griff neu zu erstellen.

type
  TCpFrame = class(TFrame)
  private
    FOnDestroy: TNotifyEvent;
    procedure WMDestroy(var Msg: TWMDestroy); message WM_DESTROY;
  published
    property OnDestroy: TNotifyEvent read FOnDestroy write FOnDestroy;
  end;

procedure TCpFrame.WMDestroy(var Msg: TWMDestroy);
begin
  if (csDestroying in ComponentState) and Assigned(FOnDestroy) then
    FOnDestroy(Self);
  inherited; 
end;

Das wird nur funktionieren, wenn das Fenstergriff des Rahmens tatsächlich erstellt. Es gibt keine andere gute Hakenspitze, also wenn Sie ihm immer Sie brauchen, um einen Flag in WMDestroy gesetzt genannt sicherstellen wollen, werden und fallen zurück in der destructor zu fordern, wenn das nicht getroffen wird.

Die Fenstergriffe sich alle in WM_NCDESTROY gelöscht, die nach all der Nachkomme WM_DESTROY Nachrichten genannt wird zurückkehren, so dass die Form und alle seine childens Griffe zu diesem Zeitpunkt noch gültig sein sollte (ohne Berücksichtigung einer, der in die befreit wurden Form des OnDestroy).

Andere Tipps

Sounds mehr wie OnClose als OnDestroy.

Wie auch immer, ich habe gerade geerbt alle meine Bilder und Formen von einer Basis Vorfahren und die OnClose Anrufe des Formulars dann alle Frames in der Komponentenhierarchie.

(Es ist nur eine Idee, aber ich habe nicht die Zeit, gerade jetzt eine Proof of Concept zu konstruieren, aber ich werde es teilen nichtsdestoweniger:)

Wenn es ein Problem mit dem Windows-Handle (n) ist, sollten Sie, ob Sie überprüfen, sind in der Lage ein Ereignis Rückrufzeiger Windows anhängen, die aufgerufen wird, wenn das Windows-Handle des Rahmens hört auf zu existiert. Vielleicht mit einer Funktion wie RegisterWaitForSingleObject

Eine weitere Option ist AfterConstruction und BeforeDestruction

außer Kraft setzen

So etwas wie folgt aus:

  TMyFrame = class(TFrame)
  private
    FOnCreate: TNotifyEvent;
    FOnDestroy: TNotifyEvent;
  protected
    procedure DoCreate; virtual;
    procedure DoDestroy; virtual;
  public
    procedure AfterConstruction; override;
    procedure BeforeDestruction; override;
    property OnCreate: TNotifyEvent read FOnCreate write FOnCreate;
    property OnDestroy: TNotifyEvent read FOnDestroy write FOnDestroy;
  end;

  implementation

  procedure TMyFrame.AfterConstruction;
  begin
    inherited;
    DoCreate;
  end;

  procedure TMyFrame.BeforeDestruction;
  begin
    inherited;
    DoDestroy;
  end;

  procedure TMyFrame.DoCreate;
  begin
    if Assigned(FOnCreate) then
      FOnCreate(Self);
  end;

  procedure TMyFrame.DoDestroy;
  begin
    if Assigned(FOnDestroy) then
      FOnDestroy(Self);
  end;
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top