VC ++ 2008 Kindelemente vom Kindelement vom tableLayoutPanel ansprechen?



  • Hallo, bin der Neue. 😄 Ich hoffe, man kann das lesen, denn meine Browser sind nicht kompatibel. Das Eingabefenster ist schwarz auf schwarz. Abschicken geht im Chrome auch nicht, habe mir ne Mail zum iPhone geschickt. Ging auch nicht. 🙁
    Jetzt mal ein Versuch im Internext Explorer...

    Ich habe in VC ++ 2008 mit Forms ein tableLayoutPanel, welches ich mit benutzerdefinieren Klassen befülle.

    So sieht eine dieser Klassen aus:

    ref class FlatButton : public System::Windows::Forms::Button {public:FlatButton(){this->FlatStyle = System::Windows::Forms::FlatStyle::System;};};
    ref class Flat2Button : public FlatButton {public:Flat2Button(){this->Font = (gcnew System::Drawing::Font(L"Webdings", 12, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point, static_cast<System::Byte>(2)));};};
    
    ref class TimerZeile : public System::Windows::Forms::TableLayoutPanel {
    ref class nam : public System::Windows::Forms::TextBox {public: nam(){this->Size = System::Drawing::Size(134, 20);this->Text = L"neue Eieruhr";};};
    ref class a15 : public FlatButton {public: a15(){this->Text = L"15";};};
    ref class aa1 : public FlatButton {public: aa1(){this->Text = L"1";};};
    ref class aa3 : public FlatButton {public: aa3(){this->Text = L"3";};};
    ref class aa9 : public FlatButton {public: aa9(){this->Text = L"9";};};
    ref class a12 : public FlatButton {public: a12(){this->Text = L"12";};};
    ref class a24 : public FlatButton {public: a24(){this->Text = L"24";};};
    ref class a48 : public FlatButton {public: a48(){this->Text = L"48";};};
    ref class tim : public System::Windows::Forms::MaskedTextBox {public: tim(){this->InsertKeyMode = System::Windows::Forms::InsertKeyMode::Overwrite;this->Mask = L"900:00:00";};};
    ref class sta : public Flat2Button {public: sta(){this->Text = L"4q";};};
    ref class del : public Flat2Button {public: del(){this->Text = L"r";};};
    public: TimerZeile(){
    this->ColumnCount = 11;
    this->ColumnStyles->Add((gcnew System::Windows::Forms::ColumnStyle(System::Windows::Forms::SizeType::Absolute, 140)));
    this->ColumnStyles->Add((gcnew System::Windows::Forms::ColumnStyle(System::Windows::Forms::SizeType::Absolute, 29)));
    this->ColumnStyles->Add((gcnew System::Windows::Forms::ColumnStyle(System::Windows::Forms::SizeType::Absolute, 25)));
    this->ColumnStyles->Add((gcnew System::Windows::Forms::ColumnStyle(System::Windows::Forms::SizeType::Absolute, 24)));
    this->ColumnStyles->Add((gcnew System::Windows::Forms::ColumnStyle(System::Windows::Forms::SizeType::Absolute, 24)));
    this->ColumnStyles->Add((gcnew System::Windows::Forms::ColumnStyle(System::Windows::Forms::SizeType::Absolute, 29)));
    this->ColumnStyles->Add((gcnew System::Windows::Forms::ColumnStyle(System::Windows::Forms::SizeType::Absolute, 29)));
    this->ColumnStyles->Add((gcnew System::Windows::Forms::ColumnStyle(System::Windows::Forms::SizeType::Absolute, 29)));
    this->ColumnStyles->Add((gcnew System::Windows::Forms::ColumnStyle(System::Windows::Forms::SizeType::Absolute, 61)));
    this->ColumnStyles->Add((gcnew System::Windows::Forms::ColumnStyle(System::Windows::Forms::SizeType::Absolute, 48)));
    this->ColumnStyles->Add((gcnew System::Windows::Forms::ColumnStyle(System::Windows::Forms::SizeType::Absolute, 22)));
    this->Controls->Add(gcnew TimerZeile::nam, 0, 0);this->Controls->Add(gcnew TimerZeile::a15, 1, 0);this->Controls->Add(gcnew TimerZeile::aa1, 2, 0);
    this->Controls->Add(gcnew TimerZeile::aa3, 3, 0);this->Controls->Add(gcnew TimerZeile::aa9, 4, 0);this->Controls->Add(gcnew TimerZeile::a12, 5, 0);
    this->Controls->Add(gcnew TimerZeile::a24, 6, 0);this->Controls->Add(gcnew TimerZeile::a48, 7, 0);this->Controls->Add(gcnew TimerZeile::tim, 8, 0);
    this->Controls->Add(gcnew TimerZeile::sta, 9, 0);this->Controls->Add(gcnew TimerZeile::del, 10, 0);this->Location = System::Drawing::Point(3, 3);
    this->RowCount = 1;this->RowStyles->Add((gcnew System::Windows::Forms::RowStyle(System::Windows::Forms::SizeType::Absolute, 26)));
    this->Size = System::Drawing::Size(459, 26);
    }
    };
    

    Dann habe ich versucht, den Buttons ein Klick-Event anzufügen. Das scheiterte nach einigen Versuchen schließlich daran, dass ich ja die Instanz des Buttons brauche, übergeben wird als sender aber die Klasse.

    Also habe ich in der Funktion, wo diese Zeilen eingefügt werden, folgenden Code:

    this->tableLayoutPanel1->Controls->Add(thetimers[i] = gcnew TimerZeile,0,this->tableLayoutPanel1->RowCount-1);
    thetimers[i]->Click += gcnew System::EventHandler(this, &Form1::DeleteTimer);
    

    Das funktioniert soweit, aber ich will ja nicht, dass die Zeile der sender ist, sondern der Button, denn ich muss ja auch die Textboxen verändern können. Nun habe ich im Debugmodus herausgefunden, dass soetwas wie dieses hier funktionieren könnte, tut es natürlich nicht:

    thetimers[i]->Controls->System::Windows::Forms::Control::ControlCollection^->System::Windows::Forms::ArrangedElementCollection^->_innerList[10]-Click += gcnew System::EventHandler(this, &Form1::DeleteTimer);
    

    Gibt es da eine Möglichkeit, auf die Kindelemente zuzugreifen oder komme ich um ein präziseres Array nicht herum?

    Das Programm soll ein Mehrfach-Wecker werden.



  • Wie du schon selbst erkannt hast, mußt du jeweils den Button-Instanzen das Click-Ereignis zuweisen.

    Es ist jedoch auch die Frage, warum du eigene Klassen für jedes der Unterelemente dafür erzeugst?
    Die Texte kannst du auch bei der Erzeugung der Unterelemente (z.B. FlatButton) zuweisen.

    Und dazu dann das Click-Ereignis zuweisen. Hier ist auch die Frage, ob du eine Click-Funktion für alle Buttons haben möchtest oder jeweils individuelle?

    Für letzteres am besten dafür dann eine Funktion erzeugen, z.B.

    FlatButton^ CreateButton(const wchar* text, System::EventHandler on_click)
    {
      FlatButton button = gcnew FlatButton();
      button->Text = text;
      button->Click += on_click;
      return button;
    }
    

    Und dann so aufrufen:

    this->Controls->Add(CreateButton(L"15", gcnew System::EventHandler(this, &Form1::DeleteTimer)), 1, 0);
    // ...
    

    Edit:
    Es müßte auch möglich sein, nur &Form1::DeleteTimer als Parameter an die Funktion zu übergeben und dann innerhalb dieser dann den EventHandler zu erzeugen - der Parametertyp ist dann ein Memberfunktionszeiger void (Form1::*)(System::Object ^ sender, EventArgs ^ e) (oder so ähnlich ;-).


    PS: Da ich selber hauptsächlich C# und C++, anstatt C++/CLI, programmiere, kann es sein, daß der Code noch Fehler enthält (z.B. fehlende ^ oder falsche Datentypen bei den Parametern).

    Außerdem ist C++/CLI nicht für die GUI-Programmierung gedacht, s.a. den gepinnten Artikel Windows Forms und Visual C++ MACHT KEINEN SINN!


Anmelden zum Antworten