Clicks von Buttons aus einem Button Array abfragen
-
Hallo!
Im CodeGear C++Builder 2007 generiere über eine Schleife einige Button innerhalb eines Arrays:
btnArray[i] = new TButton(Form1);
Wenn man die Buttons über den Designer erzeugt, werden die Click Events automatisch miterstellt. Ein einfacher Doppelklick erzeugt den leere Coderahmen der Methode im cpp-Sourcecode.
Wenn man die Buttons nun dynamisch generiert, fällt diese Möglichkeit weg. Doch wenn ich die Click Events manuell erstelle, stört er sich immer an dem Arraynamen oder irgendwas anderem. Wenn ich sie nach folgendem Schema erstelle
btnArray[i]->Click += new EventHandler(Buttons_Click);
erhalte ich wiederum solche Fehlermeldungen:
E2303 Typname erwartet E2235 Elementfunktion muß aufgerufen oder ihre Adresse übernommen werden E2379 In Anweisung fehlt ;
Wie gelingt es mir den Klick auf einen der Buttons abzufragen?
-
Schau doch mal in die FAQ.
http://www.c-plusplus.net/forum/viewtopic-var-t-is-39206.html
-
schau dir mal die FAQ-Beiträge "Dynamische Arrays von Komponenten oder Objekten", "Sendernamen bei einer OnClick-Prozedur identifizieren", "Zugriff, aber nicht durch Namen" und "zur Laufzeit erstellen, anzeigen und Events zuweisen" an
-
Wow. Danke für die Antwort. War zuvor zu stur auf Begriffe wie 'array', 'click', 'abfragen' u.ä. fixiert und bin per Suchfunktion nicht draufgestossen. Allerdings beinhaltet der o.g. Beitrag dennoch noch ein Problem. Wenn ich nach folgender Methode vorgehe
for (int i = 0; i < x; i++) { btnArray[i] = new TButton(Form1); ... btnArray[i]->OnClick=Button1Click; ... }
funktioniert das zwar erstmal wunderbar, aber ich weise allen Buttons die gleiche Methode zu. Im Prinzip bräuchte ich quasi für jeden button eine separate Methode nach dem Schema
btnArray[i] ----> Button[i]Click
so dass heweils eine andere Methode adressierbar ist.
Andererseits...
Im Prinzip gehts mir ja eigentlich nur um den Rückgabewert. Bei Klick auf Button 1 müsste eine Zahl 1 irgendwohin übergeben. Wenn ich das so mache, wie ursprünglich gedacht, hätte ich dann z.B. 7 Events mit nahezu gleichem Inhalt; ausser eben dass jeweils ein anderer Wert an eine andere Methode übergeben wird.
Mal schauen wie ich das am besten umsetzen kann. Danke erstmal für die Links. Werde ich mir gleich mal zu Gemüte führen.
-
Ferrum schrieb:
Im Prinzip bräuchte ich quasi für jeden button eine separate Methode anach dem Schema
btnArray[i] ----> Button[i]Click
so dass heweils eine andere Methode adressierbar ist.
Für das aufruferbasierte Dispatching gibt es den Sender-Parameter.
-
audacia schrieb:
Für das aufruferbasierte Dispatching gibt es den Sender-Parameter.
Oha. Ich muss leider gestehen, dass ich noch nicht allzu Fit in der Materie bin und mit diesen Berifflichkeiten in diesem Bezug erstmal nichts anfangen kann.
Aber danke dir dennoch vielmals. Immerhin weiss ich nun, nach was ich weitersuchen kann. Das ist schon sehr viel wert.
-
Irgendwie schein ich ziemlich auf der Leitung zu stehen heute...
Die ersten Möglichkeiten funktionieren tatsächlich erstklassig. Vielen Dank nochmals für alle Infos und Links.
Doch als ich es nun mit dem Sender-Parameter probiert habe, will es mir irgendwie nie gelingen die eindeutige Bezeichnung des jeweiligen Buttons auszulesen. Beispiel:
dynamic_cast<TButton*>(Sender)->Name
liefert mir lediglich einen leeren Namen zurück. Also bin ich nun hingegangen und hab in der Anfangsschleife nun noch einen dynamischen Namen vergeben, sowie die Caption gelöscht, damit der Name nicht auf den Buttons angezeigt wird. Erst dann konnte ich mit dieser Funktion den Namen abfragen bzw. weiter übergeben:
for (int i = 0; i < x; i++) { AnsiString name="btnArray_"+IntToStr(i); btnArray[i] = new TButton(Form1); ... btnArray[i]->OnClick=Button1Click; btnArray[i]->Name=name; btnArray[i]->Caption=""; ... }
Im Prinzip funktioniert es nun schon so wie es soll, aber es kommt mir dennoch etwas umständlich vor (extra Namensvergabe + extra Caption löschen).
War der Vorschlag mit dem Sender-Parameter genau so gedacht, oder ginge es noch eleganter?
-
Ferrum schrieb:
Doch als ich es nun mit dem Sender-Parameter probiert habe, will es mir irgendwie nie gelingen die eindeutige Bezeichnung des jeweiligen Buttons auszulesen. Beispiel:
dynamic_cast<TButton*>(Sender)->Name
So etwas tut man nicht. Ein dynamic_cast<> auf Zeiger gibt 0 zurück, falls der Cast nicht erfolgreich war. Da du diese Möglichkeit nicht gesondert behandelst, würde ein fehlschlagender Cast eine Zugriffsverletzung nach sich ziehen - dann könntest du ebensogut einen reinterpret_cast<> verwenden.
Korrekt geht es so:dynamic_cast <TButton&> (*Sender).Name
Im Einklang mit der Forderung, daß Referenzen immer auf ein gültiges Objekt verweisen, wirft dynamic_cast<>, falls mit einer Referenz aufgerufen, im Fehlerfalle eine Exception des Typs std::bad_cast.
Ferrum schrieb:
War der Vorschlag mit dem Sender-Parameter genau so gedacht, oder ginge es noch eleganter?
Wenn es dir lediglich um die Identifikation des Senders geht, kannst du ihn direkt vergleichen:
if (Sender == btnArray[i]) ...;
Ansonsten eignet sich auch TComponent::Tag für benutzerdefinierte Attribuierung.
-
Super. Die erstklassigen Tips sind ja hier echt genial.
Vielen Dank!