3 Stimmen

Delphi: Freigabe einer dynamischen Steuerung zur Laufzeit

Gibt es einen Ausfallschutz, um eine Delphi-Steuerelement freizugeben?

Ich habe eine TStringGrid-Abstammung, in der ich ein benutzerdefiniertes Steuerelement "einbetten", um einen Editor vor Ort zu erstellen. Wenn der Benutzer innerhalb der Zellen des Rasters über die Tabulator- oder Pfeiltasten navigiert, muss ich ein dynamisches Steuerelement erstellen, wenn die Zelle bearbeitbar ist. Ich habe die erforderlichen Ereignisse verknüpft und nutze das OnKeyDown-Ereignis meines benutzerdefinierten Steuerelements, um die Navigationsbefehle an das übergeordnete TStringGrid zurückzugeben.

Zuvor würde die TStringGrid-Nachkommenschaft einfach FreeAndNil auf dem eingebetteten Steuerelement aufrufen, aber unter bestimmten Umständen könnte dies zu Zugriffsverletzungen innerhalb von UpdateUIState/GetParentForm führen. Beim Blick auf den Aufrufstapel scheint es, dass manchmal nachdem das Steuerelement freigegeben wurde, trotzdem eine WM_KEYDOWN (TWinControl.WMKeyDown)-Nachricht auftrat.

Ich habe bereits die diskutierten Änderungen unter Wie kann ein Steuerelement innerhalb seines Ereignishandlers freigegeben werden? angesehen und umgesetzt. Dies scheint das Problem gelöst zu haben, aber ich frage mich, ob es noch andere Fallstricke bei diesem Ansatz gibt.

Im Grunde genommen hat dieser Workaround die Zerstörung des Steuerelements einfach verzögert, bis nachdem alle bestehenden Nachrichten in der Warteschlange zum Zeitpunkt der Postung der CM_RELEASE-Nachricht verarbeitet wurden.

Wäre es nicht möglich, dass nachdem CM_RELEASE gepostet wurde, eine andere WM_KEY* oder ähnliche Nachricht bereits in die Nachrichtenwarteschlange gepostet wurde?

Mein aktueller CM_RELEASE-Handler sieht wie folgt aus:

Verfahren TMyCustomControl.HandleRelease(var Msg: TMessage);
begin
  Frei;
end;

Wird dies also in allen Fällen sicher sein oder sollte ich etwas unternehmen, um andere Nachrichten aus der Warteschlange zu löschen? ( SendMessage(Self.Handle, WM_DESTROY, 0, 0) fällt mir ein )

0voto

CodesInChaos Punkte 103089

Im Allgemeinen sollten Sie ein Steuerelement nicht in einem Ereignis-Handler dieses Steuerelements zerstören.

Aber da Ihre Funktion ein einfacher nicht virtueller Nachrichten-Handler ist, der nie aus dem internen Code in diesem Steuerelement aufgerufen wird, sollte es in Ordnung sein. Mir gefällt das nicht so sehr aus stilistischer Sicht, aber ich denke, es ist für Ihren Anwendungsfall in Ordnung.

Aber eine benutzerdefinierte Nachricht wäre möglicherweise sauberer.

Wäre es nicht möglich, dass nachdem CM_RELEASE veröffentlicht wurde, bereits eine andere WM_KEY* oder ähnliche Nachricht in die Nachrichtenwarteschlange gepostet worden sein könnte?

Wenn Nachrichten in der Warteschlange große Probleme verursachen würden, könnten Sie nie sicher ein Steuerelement zerstören, da Nachrichten aus anderen Threads und Anwendungen gepostet werden können. Stellen Sie einfach sicher, dass die korrekte Funktion Ihrer Anwendung nicht davon abhängt, dass diese Nachrichten in jedem Fall verarbeitet werden.

0voto

Daniel Luyo Punkte 1316

SendMessage sendet die Nachricht und wartet darauf, dass sie zurückkehrt, deshalb können Sie sie nicht sicher im Ereignishandler des Steuerelements verwenden, das Sie freigeben.

Andererseits wird die Nachricht, die mit PostMessage gesendet wird, nach dem Verlassen des Ereignisses verarbeitet (wenn es keinen weiteren Code im Ereignis gibt).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X