[MSVS 2005 C++] Referenzen / Controlverweise zu Containern hinzufügen

the incredible Leitman

Erfahrenes Mitglied
Hallo erstmal liebe Tutorials.de user ^^
Und alles Gute im neuen Jahr :D

Ich habe nun seit knapp 5 Stunden alles mögliche über mein Problem gesucht, leider aber nichts gefunden, das mir irgendwie weiterhelfen könnte... vl fehlen mir einfach noch ein paar Grundkenntnisse, was das angeht...

also, ich habe eine Anwendung, die mehrere Tab Controls mit mehreren Tab Pages öffnet...

Nun möchte ich auf diesen Tab Pages gewisse Controls platzieren und zwischen diesen auch Funktionalitäten implementieren...

Leider komme ich mit dem Erstellen und Zuweisen der Controls noch nicht ganz klar...
Ich brauche z.B. ein Label, das mir die Zeit anzeigt...
Dieses Label soll in jeder einzelnen TabPage, rechts oben angezeigt werden und durch ein Event aufgefordert werden sich zu aktualisieren...
also ein Timer sagt jede Sekunde label->getTime() // Pseudocode ^^

Nun weiß ich aber nicht genau, wie ich dieses Label auf die Form (TabPage) bringe

Muss ich da für jede einzelne Page in jedem einzelnen Control ein eigenes Label erstellen? Oder wie kann ich lediglich einen Verweis auf dieses Label adden?

Ich habe schon einiges probiert, bin aber auf keine Lösung gestoßen:
C++:
this->tabPage->Controls->Add(&Label);
==> so gehts nicht, error C2440!
wenn ichs vorher in ein Label casten versuche -> error C2664

C++:
// Pseudocode
...
array<TabControl ^> ^m_tabs;
array<TabPage ^> ^m_pages;
...

for each (TabControl ^tc in this->m_tabs)
{
    for each (TabPage ^tb in this->m_pages
    {
        Label ^label = gcnew Label();
        ...
        tb->Controls->Add(label);
    }
}
somit erstelle ich für jede TabPage ein neues Label


C++:
// Pseudocode
...
array<TabControl ^> ^m_tabs;
array<TabPage ^> ^m_pages;
...
Label ^label;

for each (TabControl ^tc in this->m_tabs)
{
    for each (TabPage ^tb in this->m_pages
    {
        label = gcnew Label();
        ...
        tb->Controls->Add(label);
    }
}
so wird das eine Label immer neu instanziert

und wenn ich überhaupt nur vorher ein Label erstelle, dass ich dann in die Tabs hinzufüge will:
C++:
// Pseudocode
...
array<TabControl ^> ^m_tabs;
array<TabPage ^> ^m_pages;
...
Label ^label = gcnew Label();

for each (TabControl ^tc in this->m_tabs)
{
    for each (TabPage ^tb in this->m_pages
    {
        ...
        tb->Controls->Add(label);
    }
}
wir immer nur in der allerletzen Page das Label geadded -.-

Bitte, ich verstehs nicht... ich dachte, wenn ich ein Control in eine Form adde, wir nur die Referenz genommen? Wieso kann ich dasselbe Control dann nicht woanders auch adden :confused:

ich erstelle mit "Label ^label" ja noch kein Label oder? ich reserviere lediglich den Speicher für ein Object oder?
erst wenn ich "label = gcnew Label()" definiere, wird ein Label erstellt, stimmt das?

Wie kann ich das lösen, z.B., auch wenn ich eine Listbox (oder irgendwas, in dem Datengespeichert werden können) habe,
dass ich zum Beispiel in einer Page auf diese ListBox zugreife,
und dieselbe ListBox in einer anderen Form aktualisiert wird

Ich glaube mit fehlt hierbei noch ein wesentlicher Bestandteil um das komplett zu verstehen... ich wüßte aber nicht einmal, wonach ich genau suchen sollte?
Fällt das unter Intitalierung / Deklaration / Speicherassoziierung
 
Zuletzt bearbeitet:
Muss ich da für jede einzelne Page in jedem einzelnen Control ein eigenes Label erstellen? Oder wie kann ich lediglich einen Verweis auf dieses Label adden?
Du müsstest deine GUI nach den Labels "abgrasen" um sie ermitteln zu können. Erstellen tust ja deine GUI im Designer. Daher musst also eine Basisfunktionalität in deine Controls einpflegen um diesem Aufwand zu umschiffen. Also von den entsprechenden Controls ableiten...

ich erstelle mit "Label ^label" ja noch kein Label oder? ich reserviere lediglich den Speicher für ein Object oder?
erst wenn ich "label = gcnew Label()" definiere, wird ein Label erstellt, stimmt das?
Mit reservieren meinst definieren. Ja, da wird lediglich der Speicher reserviert. Und Du es nun instanzierst, deklarierst es es mit einer neuen Instanz seines Typs und der reservierte Speicher wird damit gefüllt.

Wie kann ich das lösen, z.B., auch wenn ich eine Listbox (oder irgendwas, in dem Datengespeichert werden können) habe,
dass ich zum Beispiel in einer Page auf diese ListBox zugreife,
und dieselbe ListBox in einer anderen Form aktualisiert wird
Wie gesagt, Du musst in dem Fall von den entsprechenden Controls ableiten.

Ich glaube mit fehlt hierbei noch ein wesentlicher Bestandteil um das komplett zu verstehen... ich wüßte aber nicht einmal, wonach ich genau suchen sollte?
Fällt das unter Intitalierung / Deklaration / Speicherassoziierung
Weder noch. Hier geht es eindeutig um die OOP und deren Werkzeuge. :)

Ich habe Dir mal einen Demo mit einem Component TimeLabel gemacht. In dem Component befindet sich ein statisch definierter Timer, sowie als auch Methoden um ihn zu starten und zu stoppen. Dann habe ich mithilfe der Syste.Design.ControlDesigner Klasse das Property Control.Text aus dem Designer entfernt und als Ersatz dafür das Property namens TimeLabel.DateTimeFormat hinzugefügt.
 

Anhänge

  • 27633attachment.zip
    75,9 KB · Aufrufe: 13
Zuletzt bearbeitet:
Danke erstmal für diese wirklich aufschlussreiche Demo, die hat mir wirklich echt weitergeholfen ^^

Habe trotzdem noch ein paar Fragen / Anregungen zum Verständnis
Du müsstest deine GUI nach den Labels "abgrasen" um sie ermitteln zu können. Erstellen tust ja deine GUI im Designer.
Naja, nicht wirklich...
der C++ Designer ist bei weitem nicht so toll wie in C#,
Wenn auch nur kleinste Teile im Code enthalten sind, die er nicht versteht oder für nicht richtig hält, wird nichts mehr angezeigt...
Da die Basisklasse meiner Controls kein WindowsControl ist,
wenn ich vorm Konstruktor Variablen definiere,
wenn ich eine Generic List verwende... etc, etc... funktioniert mein Designer nicht mehr :(
CodeDOM parser error,
Internal error,
HRESILT E_FAIL,
...
Aber ich habe mich mittlerweile daran gewöhnt, ohne dem zu arbeiten... früher gabs den ja auch nicht ^^
Genau wie Intellisense... Das funktioniert auch nur mal ab und zu, wenns grade Bock hat...

:offtopic: wenn jemand weiß, wie man Intellisense schnell und problemlos updaten kann, bitte Hilfe...
einfach löschen und VS neu starten bringt gar nüschts... da wird zwar ein neues file erstellt, aber das ist genauso verplant wie das jetzige -.-
:/offtopic:

Daher musst also eine Basisfunktionalität in deine Controls einpflegen um diesem Aufwand zu umschiffen. Also von den entsprechenden Controls ableiten.....
...
Du musst in dem Fall von den entsprechenden Controls ableiten.
ok, jetzt komm ich nicht mehr mit...

Ich glaube ich habe die falsche Frage zu ausführlich beschrieben -.-
Das mit den Labels war nur ein Paradebeispiel,
um mein Problem zu erläutern, aber prinzipiell habe ich das Problem, mit quasi "shared Controls" :(

btw: Trotzdem, das mit dem TimeLabel ist echt toll, das hat ein weiteres meiner Probleme gelöst thx

Ich versuchs mal anders zu formulieren...

also ich habe z.B. einen Control, der eine bestimmte Funktion implementiert auf meiner Form. Außerem kann ich in dieser Form weitere Childforms öffnen (so wie Menüführung)
hmm, sagen wir einmal, das ist ein echt wichtiges Control, das...
was weiß denn ich...
den Higscore von Solitär anzeigt und bei Click Solitär öffnet und von jeder dieser Unterforms aktivierbar sein soll ^^

Genau dasselbe wie mit TabPages => das Control soll von jeder Page erreichbar sein

So, worauf ich eigentlich hinaus will,
Gibts da eine Möglichkeit, mit de rich diese Controls "shared" oder so mache

Also, wenn ich in allen TabPages, ein (wieder nur ein Beispiel) Label habe, in dass ich einen Text schreibe,
soll dass auch in jedem Label aktualisiert werden
und sich so verhalten, als ob es EIN Control wäre

ungefähr klar?

also ich mach in TabControl 1 die Page 3 auf, schreibe in das label "Score 500"...
dann mach auf TabControl 3 auch die Page 3 auf (die eben dasselbe ist wie auf TabControl 1 nur auf nem anderen Bildschirm) und dort soll in dem label auch "Score 500" stehen

Wenn ich das wiederum hier ändere, soll es ebenfalls in jedem Tab auf jedem Control geändert werden...

und genau DAS ist mein Problem -.-

Gitbs diese Möglichkeit von shared Controls?
Logisch gesehen würde ich ja einfach
C++:
// Pseudocode
array<TabPage ^ > ^tabPages;
...
tabPages[0]->Controls->Add(label);
tabPages[1]->Controls->Add(label);
tabPages[2]->Controls->Add(label);
...
schreiben, aber das geht eben nicht...

Wie kann ich das lösen?
Muss ich für jede Page, jedes Tab ein eigenes Control erstellen?
Und dann immer, wenn eine Aktion dieses Controls durchgeführt wurde, die gesamte Form mit allen TabControls durchgehen und diese Aktion bei allen gleichen Controls nachziehen?
Das kanns ja nicht sein oder...
Ich mein, hier spreche is von einem Label und so... aber im Endeffekt habe ich ja 4 (oder mehr) TabControls * 8 Pages * XXX Controls (eben unterschiedlich und noch nicht klar, aber mindestens 3) = 96 Controls...

Oder wenn ich jeweils alle Controls auf einer TabPage als quasi "TabPage1Control" zusammenfasse und als eigenes Control behandle...würde das etwas ändern? Hab leider kaum Ahnung von Speicherausslastung und Verbrauch oder Schnelligkeit :(
Nur bin ich eben bei dem TimeLabel darauf gekommen... Ich müsste jede Sekunde für jedes TabControl, jede TabPage nach jedem Control durchwühlen, das ein Label ist und den Namen "DateTimeLabel" hat und dessen Wert aktualisieren... Das kann doch nicht effizient sein oder


Daher kamm ich auf Controls, auf die man von überall zugreifen kann...braucht man so eine Mögllichkeit denn nicht?

Oder bin ich wieder mal einfach nur komplett verplant und mach mir die ärgsten confusen Gedanken ber etwas, das in wirklichkeit komplett einfach ist

Hoffe, das war irgendwie klar verständlich...
hm....vl kann ich ja ein Bild in Paint dazumalen

mfG
Leitman
 
Zuletzt bearbeitet:
hm... ich weiß nicht, ob ih aus meiner geistigen Verwirrung herausgefunden habe, aber ich habe e einmal (wieder ans Beispiel mit den Labels) folgendermaßen gemacht:
C++:
void ZLSClient::ZLSClientApplication::SetTime() 
{
	// wird aufgerufen bei jedem Timer Tick
	
	for each (TabControl ^tabCtrl in this->m_tabControls)
	{
		for each (TabPage ^tabPg in tabCtrl->TabPages)
		{
			for each (Control ^ctrl in tabPg->Controls)
			{
				if (ctrl->Name == "groupBoxUhrzeitDatum")
				{
					for each (Control ^gbCtrl in ctrl->Controls)
					{
						if (gbCtrl->Name == "Uhrzeit/Datum")
						{
							gbCtrl->Text = Convert::ToString(System::DateTime::Now);
						}
					}
				}
			}
		}
	}
}
XD

Also, so funktionierts schonmal...

aber ich weiß nicht, ob dass vom Rechenaufwand, Speicherverbrauch...etc, etc vertretbar ist...

Diese Vorgangsweise kommt mir sehr strange / russisch vor,
nur um an ein Control heranzukommen

Hättet ihr vl eine andere Lösung parat?
Ansonsten werd ich einfach eine Methode implementieren, die einen String, den Namen des Controls übernimmt und dann alles durchsucht, nach diesem Control?

vielen Dank, ihr seid wunderbar ^^

mfG
Leitman
 
Also dein Problem habe ich schon verstanden.
Du möchtest eine Basisfunktionalität für ein Control eines bestimmten Typs anbieten und alle Instanzen dieses Typs sollen nun auf diese bestimmte Aktion reagieren.
Nichts anderes passiert bei dem TimeLabel.

Die Basisfunktionen TimeLabel.StartTimeUpdating() und TimeLabel.StopTimeUpdating() werden von dem Typ TimeLabel als statische Methoden angeboten und lösen das statische Ereignis TimeLabel.UpdateText intern aus. Wenn nun ein Objekt aus dem Typ TimeLabel instanziert wird, abonniert jede Instanz dieses statische Ereignis und alle Instanzen reagieren demzufolge zur gleichen Zeit auf dieses Ereignis.

Die Aktion wird also demzufolge von dem Typ ansich zu allen Instanzen des Typs weiter geleitet, ohne dafür extra Code schreiben zu müssen, um jede Instanz erst mal im Programm lokalisieren zu können.

Hast jetzt das Prinzip von dem TimeLabel verstanden? :)
 
Zuletzt bearbeitet:
Ah jetzt ja...
*Lichtaufgeh*

Verstehe schon, also muss ich alle Controls die ich verwende von den StandardControls ableiten und quasi so eine WennMultiTab-Funktion implementieren?
Dann brauche ich nicht jedesmal alles duchsuchen...hm.... das hört sich gut an ^^

Vielen, vielen Dank, das hat mir echt weitergeholfen :D *freu*

Aber, nur interressehalber, es gibt KEINE Möglichkeit, ein und dassselbe Control mehrmals in derselben Anwendung zu adden, oder?
Hab irgendwas gefunden über "shared Controls", aber das war aus ASP.NET :(

Ahja, und gleich nochwas *gg*
(hast eh glaube ich du mir vorgeschlagen) Wenn ich nun alles Controls und Elemente, die ich auf einer TabPage verwende zu einem CustomControl zusammenfasse (also z.B.: TabPage1Control) geht dadurch nicht die Flexibilität verloren?
Was für Vor- und Nachteile hätte ich dadurch?
Das Control müsste ich dann einfach von TabPage ableiten und eben meine benötigten Funktionen / Controls hinzufügen, oder?

Nochmals vielen Danke mein Lehrer ^^
mfG
und schönen Tag noch

Leitman
 
Also normaler Weise gehören die ganzen Controls, die sich um eine bestimmte Aufgabe kümmern, zu einem UserControl zusammengefasst. Daraus ergibt sich, dass man diese UserControls wiederum überall weiterverwenden kann. Du diese ergo auch auf unterschiedlichen PabPages anzeigen kannst. :)
 
ok Danke :D

Also, wenn ich nun für jede TabPage die ich brauche (8 an der Zahl [vorerst ^^]) ein eigenes Control erstelle und die alle in einer .dll zusammenfasse, muss ich einfach dann diese DLL mit in mein Programm einbinden... eigentlich klar soweit ^^

Na gut, dann mache ich mich mal an die Arbeit
Nochmals vielen Dank Cosmo, das hat mich sehr weit gebracht

mfG
Leitman

,/ erledigt
 
Bin eben auf einen besseren Lösungsweg, als die von mir erstellte Suchfunktion (siehe oben) gestoßen ^^

Nach der Erstellung der einzelnen Controls, adde ich sie einfach zu einer Liste desselben Typs... Nun kann ich wenn ich ein Property ändern möchte, einfach alle Einträge dieser Liste abgrasen und die Änderung nachziehen ^^

Vorgangsweise anhand des Label Beispiels:
C++:
// Pseudocode
...
// im Headerfile deklarierte Labels Liste wird erstellt:
this->m_timeLabels = gcnew List<Label ^>(0);
...
// for each Tab Page in each TabControl 
// Label wird erstellt:
Label ^m_UhrzeitDatumLabel = gcnew System::Windows::Forms::Label();
m_UhrzeitDatumLabel->AutoSize = true;
m_UhrzeitDatumLabel->Text = Convert::ToString(System::DateTime::Now);
m_UhrzeitDatumLabel->Font = gcnew System::Drawing::Font("Arial Narrow", 22, System::Drawing::FontStyle::Bold);		
m_UhrzeitDatumLabel->Location = Point (25, 20);
// Label wird zur Liste geadded:
this->m_timeLabels->Add(m_UhrzeitDatumLabel);
...
// bei jedem Timer Tick, soll der Label->Text die aktuelle Zeit annehmen:
// Timer Tick Metode:
for each (Label ^lab in this->m_timeLabels)
{
	lab->Text = Convert::ToString(System::DateTime::Now);
}

so gehts auch voll super,
und diese Lösung gefällt mir derweil am Besten ^^
 
Und da ist er schon wieder und stellt unsinnige Fragen ^^

Erstmal, soll ich für das Thema nen neuen Thead aufmachen?
Eigentlich ist es ein neues Thema, dass aber im Laufe dieses Problems bereicht erwähnt wurde (!)

Also, eh geht um meine TabPages, die ich jetzt alle in eine .dll verpacken möchte

Dazu hab ich ein neues Project (Windows Forms Control Library) erstellt in dem ich nun einen Reihe von Controls hinzufüge...
Diese leite ich alle von System::Windows::TabPage ab... logisch irgendwie ^^

Mein Problem ist nun, wie kann ich diese TabPages dann zu einem TabControl adden? :confused:

wenn ich einfach versuche
C++:
tabControl->Controls->add(MyTabPage);
erhalte ich nen error, dass nur TabPages zu TabControls hinzugefügt werden können

wenn ich nen cast versuche, bekommen ich
"When casting from a number, the value must be a number less than infinity.
Make sure the source type is convertible to the destination type"

Was kann ich da machen?

Oder muss ich meine ganzen Controls, Funktionen...etc. in ein...was weiß ich-Control geben und kann das dann zu meiner TabPage in der Anwendung hinzufügen?

Hab gerade nen Hänger, hoffe mir kann einer von euch etwas helfen :-(
Bitte ^^
 
Zurück