Probleme mit zur laufzeit erstellten Labels
-
Hallo,
ich habe folgendes Problem ich erstelle in meinem Programm mehrere Labels zur Laufzeit. Nun soll es so sein das beim Click auf ein Label das Label gelöscht werden soll. Dies hab ich folgendermaßen realisiert:
void __fastcall TForm1::FormCreate(TObject *Sender) { Test = new TLabel(this); Test->Caption = "Hallo"; Test->OnClick = DeleteClick; Test->Parent = this; } //------------------------------------------------------- void __fastcall TForm1::DeleteClick(TObject *Sender) { delete Sender; }
Leider erscheint beim Klicken auf das Label die Meldung
... Access Violation at adress ... in module VCL50.bpl
Bei normal zur entwicklungszeit erstellten Labels klappt das ohne Probleme...
Ich hoffe ihr könnt mir weiterhelfen
Danke schon im voraus
-
vielleicht statt delete Sender mal Sender->Destroy verwenden.
-
Hallo,
so klappt es leider auch nicht.
-
Hmm, was kommt für ne Fehlermeldung?
-
delete Test;
-
sieht mir nicht nach ner Fehlermeldung aus
eigentlich müsste beides gehen, andernfalls liegt vielleicht woanders der Fehler.
-
KeinBenutzername schrieb:
Hallo,
Leider erscheint beim Klicken auf das Label die Meldung
... Access Violation at adress ... in module VCL50.bpl
Bei normal zur entwicklungszeit erstellten Labels klappt das ohne Probleme...
Das problem liegt daran, dass nach dem aufruf von DeleteClick kehrt die funk zurück, aber objekt, das die funktion aufgerufen hat, gibt es nicht mehr. frag mich nicht, warum es mit der "normal zur entwicklungszeit erstellten Labels" klappt. vielleicht teusche ich mich auch. aber ich hab es folgendermasse gelöst:
*.CPP
// in deiner DeleteClick void __fastcall TForm1::DeleteClick(TObject *Sender) { PostMessage(Handle, 29456, 0, (long)Sender); //löschen veranlassen } // die eigentliche löschroutine void __fastcall TForm1::DeleteLab(TMessage &Msg) { delete (TObject*)Msg.LParam; }
*.HPP
... private: // Anwender-Deklarationen void __fastcall DeleteLab(TMessage &Msg); ... public: ... BEGIN_MESSAGE_MAP VCL_MESSAGE_HANDLER(29456, TMessage, DeleteLab) END_MESSAGE_MAP(TForm);
-
Frage am Rande: Wo ist "Test" deklariert?
Bin mir grad nicht sicher, aber caste vor dem Delete mal den Sender nach TLabel...
-junix
-
Also ich habe es jetzt mal genauso wie "KeinBenutzerName" gemacht, wobei ich Test mal als Private und mal kurz vor dem Erstellen definiert habe. Hat funktioniert. Allerdings habe ich das nicht in OnCreate gemacht, sondern in nem ButtonClick Ereignis. Als ich das dann mal in der OnCreate Methode der Form gemacht habe, tauchte der Fehler auch auf. Also eine Zugriffsverletzung. Also liegt das irgendwie bei OnCreate...
MfG Aoeke
-
Ah, da kommt mir ne Idee: Wenn bei mir was im onCreate nicht funzt, dann nehm ich immer onActivate, probiers mal, vielleicht geht's ja, hängt bestimmt damit zusammen, dass einige Sachen bei onCreate noch nicht existieren, aber bei onActivate schon.....kommt mir zumindest so vor.
-
Habs grad ausprobiert, die Cast-Idee bringt nix...
@Xqgene Das von dir beschrieben ist kein Problem, denn die Funktion existiert ja nach wie vor (gehört ja TMyForm)
Wenn du obiges Kreuzchen setzen möchtest, dann weise bitte auch auf die Gefahren hin, welche dieses Event mit sich bringt.-junix
-
Dann deklarier halt ne Bool-variable in Private oder Public und setz die auf true bei onActivate, und davor noch die Abfrage if(!Boolvariable) {.....}, wo ist das Problem?
-
Ich sagte, du sollst auf die Gefahren hinweisen. Nicht irgendwelche halbgare Lösungsvorschläge posten für Probleme die anderen vielleicht noch gar nicht sehen.
-junix
-
Na ich weiß ja nichtmal was du meinst, ich meine ich mach das bisher immer so und bei mir ist nie irgendwie etwas doppelt gelaufen. Und zur Sicherheit kann man ja ne Bool-variable nehmen.
-
Ganz einfach: Du solltest darauf hinweisen, dass OnActivate bei jedem mal, wenn das Fenster den Fokus erhält neu ausgeführt wird.
-junix
-
Ahso, ok, mom....
Hinweis: onActivate reagiert immer dan, wenn das Fenster den Fokus bekommt!
Mal im Ernst, wo ist jetzt dein Problem? -nimm einfach wie ich sagte ne Bool-variable.
-
hallo,
@junix: das ist falsch. bei mdi-anwendungen mag OnActivate jedes mal wenn das fenster den focus erhält ausgeführt werden, nicht aber bei "normalen" sdi anwendungen. bei den sdi-anwendungen tritt OnActivate nur dann auf, wenn von einem fenster der selben anwendung der fokus auf das fenster mit OnActivate gesetzt wird, nicht aber, wenn zwischen fenstern anderer anwendungen der fokus gestzt wird. so tritt OnActivate also lange nicht so oft auf als man denkt, und wenn die anwendung nur ein fenster hat, tritt OnActivate einmal, nämlich nach dem startvorgang auf...
mfg
murph
-
Hallo,
erst mal schonmal danke für die rege beteiligung.
Ich habe auch schon einiges ausprobiert, aber es klappt einfach nicht. Was ich mir vorstellen kann, das den zur entwicklungszeit erstellten Label noch irgendwo irgende eine zuweisung gemacht wird, die ich nicht kenne (eine Zuweisung wie z.B. Label->Parent = this) und die ich demzufolge auch nicht zugewiesen hab. Nur alle Funktionen und propertys ausprobieren ist sehr umständlich...
ich hoffe das bals eine Lösung gefunden wird.
-
hallo,
warum reicht es dir eigentlich nicht aus, die label-instanzen unsichtbar zu machen? in der art:
void __fastcall TForm1::ClickLabel(TObject* Sender) { dynamic_cast<TLabel*>(Sender)->Visible = false; }
warum es bei einer freigabe durch den destructor zu einer zugriffsverletzung kommt ist mir momentan noch nicht ganz klar, mal sehen...
mfg
murph
-
Wobei dein Code äusserst ungeschickt ist, murph... betrachte mal genau die Rückgabewert-Definition von dynamic_cast...
-junix