Button im eigenen onClick Ereignis löschen
-
Hallo,
Folgendes Problem:
Ich erzeuge zur Laufzeit in einem StringGrid am Ende Jeder Zeile einen BitButton. Die Buttons werden in einem Array verwaltet. Der Button dient dazu die entsprechende Zeile zu löschen. Das funktioniert ja auch problemlos.Aber: Ich führe in der OnClick Methode eine Funktion aus die die Zeile und den Button löscht. Danach folgen keine weitren Anweisungen. Das Problem ist nur das danach eine Exception ausgelöst wird bevor die Onclick() Methode beendet wird da die Instanz dieser Funktion ja mit dem Button gelöscht wurde. Wie könnte ich es hinkriegen das der Button erst gelöscht wird wenn die OnClick Funktion beeendet ist. (Ohne jetzt einen Timer benutzen zu müssen; fände ich jetzt nicht so elegant).
Mfg Mav
-
Kannst Du den Button nicht in der darauffolgenden Methode löschen? Oder läuft Dein Prog nicht so logisch ab?
MfG
-
Der gängige Weg wäre wohl, nur einen Button zu erzeugen und diesen nur in der jeweils aktiven Zeile anzuzeigen. Schau mal hier: http://www.bytesandmore.de/rad/cpp/snipp/sc02038.php
-
nun ich hatte ein ähnliches problem, mit einem Array von Images, die auf ein Klick auf derselben gelöscht werden mussten.
Gelöst habe ich es über eine PostMessage.
Diese ruft z.B. ein DeleteButton auf, und das ganze pfunkt ohne Fehlermeldungen.Gruß
Wes
-
Habe gerade mal das hier ausprobiert:
void __fastcall TForm1::FormShow(TObject *Sender) { TButton* btn = new TButton((TComponent*) 0); btn->Parent = this; btn->OnClick = handleOnClick; } void __fastcall TForm1::handleOnClick(TObject *Sender) { TButton* btn = (TButton*) Sender; delete btn; }Das funktioniert einwandfrei. (BCB 2006)
Gruß
Alexander
-
@Alexander Kempf: is ja interessant. bei mir wird da eine Zugriffsverletzung oder ein EAbstractError ausgelöst (BCB6). Aber funktionieren tuts schon. es tut ja was es soll, nur das eben eine Exception ausgelöst wird.
@joe_M : ich kenne das Beispiel hat mir auch schon geholfen. Aber ich wollte eben in jeder Zeile einen Button haben.
@Kolumbus: was heißt da Nachfolge Methode. Wenn isch nach dem Löschen im OnClick Ereigenis eine weitere Funktion ausführe wartet die Onclick Methode ja auch bios diese beendet wurde bevor sie sich selbst beendet.
Aber die Sache mit dem PostMessage kling interessant. Werde ich mir mal anschauen. kannte nur SendMessage und das hätte nichts an meinem Problem geändert
-
Ich hab das auch gerade mal ausprobiert (ebenfalls BCB6). Ich bekomme auch eine Zugriffsverletzung...
Ein Tip zum Thema PostMessage: Verwende kein ApplicationEvents-Objekt zum empfangen der Botschaften, sondern erstelle einen VCL_MESSAGE_HANDLER, spart Dir eine Menge Sucherei nach dem Fehler, wenn Dir Botschaften 'verloren' gehen.
-
Naja, bin halt noch nich so der C++/VCL - Checka. Meinte aber nicht, dass Du ne Funktion im Btn-Click-Ereignis aufrufen sollst (ist ja klar das da dasselbe rauskommt), sondern einfach den Btn irgendwo im nachfolgenden Code entfernen... Nachdem das Btn-Click-Ereignis beendet ist.
MfG
-
Das Problem hatte ich auch und ich habe es so gelöst, daß ich mir ein dyn. Array erzeugt habe, in das ich die Buttons (bzw. ganz allgemein Controls) gepackt habe und diese dann an geeigneter Stelle gelöscht habe (z.B. in einer OnUpdate-Funktion).
typedef VCtrl std::vector<TControl *>; VCtrl m_vErased; // als private Member von TForm1 void __fastcall TForm1::handleOnClick(TObject *Sender) { TButton* btn = (TButton*) Sender; btn->Visible = false; // anstatt delete m_vErased.push_back(btn); } void TForm1::OnUpdate() { // wirkliches Löschen aller gelöschten Controls -) for(VCtrl::iterator it=m_vErased.begin(); it!=m_vErased.end(); ++it) delete (*it); m_vErased.clear(); }Da du die Buttons ja sowieso schon in einem Array hast, kannst du ja evtl. einfach überprüfen, ob sie unsichtbar sind und dann entsprechend löschen.
-
Hilft es denn, wenn Du vor dem Löschen die OnClick-Eigenschaft auf null setzt?
Also so:void __fastcall TForm1::handleOnClick(TObject *Sender) { TButton* btn = (TButton*) Sender; btn->OnClick = 0; delete btn; }Nur geraten...
Gruß
Alexander
-
@Th ist zwar irgendwie auch geschummelt, aber ist natürlich auch ne Möglichkeit.

Die PostMessage Geschichte gefällt mir zwar prinzipiell besser, nur habe ich mich damit noch gar nicht beschäftigt und hab dazu jetzt auch nicht die Zeit.Daher werde ich mal Deine Lösung in Betracht ziehen.
schon mal danke
Mfg mav
-
Alexander Kempf schrieb:
Hilft es denn, wenn Du vor dem Löschen die OnClick-Eigenschaft auf null setzt?
Nee, leider nicht...
-
Das mit dem PostMessage ist nicht so schwierig:
// Header des Forms // irgendwo über der Klassendefinition #define CM_DELETEBUTTON (WM_APP + 400) // unter private oder protected void __fastcall CMDeleteButton(TMessage Message); BEGIN_MESSAGE_MAP VCL_MESSAGE_HANDLER(CM_DELETEBUTTON, TMessage, CMDeleteButton); END_MESSAGE_MAP (TForm) // CPP des Forms void __fastcall TForm1::CMDeleteButton(TMessage Message) { // hier der Code zum Löschen des Buttons // am sinnvollsten ist wohl als LParam oder WParam der Botschaft einen Zeiger auf den Button zu übergeben TButton* btn = (TButton*) Message.LParam; delete btn; } // Aufruf dann aus der Button-Click Mehtode über PostMessage(Form1->Handle, CM_DELETEBUTTON, 0, (int) this);
-
Hallo
@Braunstein : Die Methode muß natürlich überall CMDeleteButton heißen

... void __fastcall TForm1::CMDeleteButton(TMessage Message) ...bis bald
akari
-
@Joe_M: Wirklich vielen Dank! Werde ich nachher mal ausprobieren. Weil aus der BCB Hilfe habe ich jetzt nicht auf die Schenlle verstanden wie das funzt.
Danke
Mfg Mav
-
@akari
Hiermit hatte ich ausnahmsweise mal nichts zu tun.
-
Hallo,
habs jetzt mal ausprobiert. funktioniert super vielen Dank!
Mfg Mav
-
Hallo
Braunstein schrieb:
@akari
Hiermit hatte ich ausnahmsweise mal nichts zu tun.
Sorry... ich weiß gar nicht warum ich dort Braunstein geschrieben habe...

bis bald
akari
-
akari schrieb:
Die Methode muß natürlich überall CMDeleteButton heißen

Ich hab das einfach kopiert, geändert und die angesprochene Stelle vergessen... Ich habs geändert.