none
Wieso, Weshalb, Warum? Geänderte Rahmenfarbe aber auch beibehalten RRS feed

  • Frage

  • Hallo Leute!

    Erst einmal ein frohes neues Jahr und lieben Dank für Eure Hilfe.

    So mein Pong läuft dank Koopakiller soweit. Jetzt habe ich aber doch noch einige Fragen, die mir so nicht klar sind.

    Mit den Methoden:

    Color liefereBackColor()
    		{
    			return colorDialog1->Color;
    		}
    
    		Color liefereRahmenColor()
    		{
    			return rahmenFarbe;
    		}

    Wir die jeweils ausgewählte Farbe an die Form1 übergeben. Doch bevor dies geschieht, muss im Methodenkopf des Konstruktors noch mit einem Color-Parameter erweitert werden und sieht dann so aus:

    einstellungenDialog3(Int32 breite, Int32 hoehe, Color rahmen, Color malen)

    OK das Color malen ist jetzt ein Versuch die neu Farbe beim wieder Öffnen der Form2 zu behalten und gehört noch nicht dazu.

    Dem Parameter übergebe ich mit der Anweisung:

    rahmen = rahmenFarbe;

    In der Form1 wird beim Aufruf der Form2 ein this-Zeiger für die rahmenFarbe als Parameter gesezt und sieht dann so aus:

    einstellungenDialog3 ^neueWerte = gcnew einstellungenDialog3(this->Width, this->Height, this->rahmenFarbe, this->malen);

    this->malen bitte einfach weg denken. Nächste Anweisung wäre dann (ShowDialog...).

    Bevor ich dann meinen Rahmen, den Ball und den Schläger in der gewählten Farbe zeichnen lasse, muss ich den Color Typ rahmenFarbe noch in der Form1 bekannt machen, weil der Compiler sonst nicht meine this->rahmenFarbe nicht kennt. Dieser rahmenFarbe weise ich dann die Startfarbe Weiß zu. Auf der Form1.

    Jetzt tauchen meine Fragen auf.

    Warum kann ich dem Pinsel auf der Form1 nicht mit der Anweisung "pinsel->Color = neueWerte->RahmenColor();" nicht die neue Farbe zuweisen? Oder mit "pinsel->Color = rahmenFarbe"? (Typen sind Color und Brush und die scheinen sich nicht miteinander grün zu sein). Bei den Anweisungen "Ball->BackColor = ... und Schlaeger->BackColor = .. das Selbe.

    Wieso aber funktioniert das in den Methoden "zeichneSpielfeld()", "neuerBall()", "zeichneZeit()" und "zeichnePunkte()" in der Form1? Natürlich erst nach dem vorherigem neu Aufruf der entsprechenden Funktionen nach dem Schließen der Form2.

    Wie zum Kuckuck kann ich der "malflaeche" auf meiner zweiten Form dazu bringen, meine Farbeinstellungen auch nach dem Schließen bei zu behalten? Was mir einfällt ist, dass ich dafür sorgen muss, das die Farbe vor dem Schließen der Form2 in einer Variable speichern sollte. Oder in deren Konstruktor nochmal meine Methode "maleVorschau()" aufrufen müsste. Der Aufruf funktioniert nicht. Hab es mit Paint, Graphics und Color versucht, aber ich komme nicht darauf. Einfach währe ein nochmaliger Aufruf meiner "malfläche"  mit den neuen Farbeinstellungen vor dem Schließen der zweiten Form.

    Eins stell ich bei diesen Aufgaben fest. Grafik in C++/Cli und Form ist irgendwie nicht meins. Aber ist es in C# den anders? Einfacher?

    Nicht des do trotz muss ich für meine schriftliche Ausarbeitung die Zusammenhänge verstehen. Also Wieso, Weshalb und Warum ist das so.

    Lieben Dank

    lempy

    Mittwoch, 1. Januar 2014 16:57

Antworten

  • Hey Koopakiller

    Habe das Rätzel gelöst!!!!! Dank eines anderen Forums, wo mir jemand mitgeteilt hat, dass die Farbe schon da ist auf der Form2. Nur ich würde nichts damit tun. Nach einigem Hin und Her hat er mir dieses Codefragment gezeigt:

    Farbdialog(Color HintergrundFarbe, Color RahmenFarbe)
    {
    	InitializeComponent();
    	//
    	//TODO: Konstruktorcode hier hinzufügen.
    	//
    	LinienBreite = 6;
    	pinsel1 = gcnew SolidBrush(Color::White);
    	malflaeche = panelVorschau->CreateGraphics();
    	panelVorschau->BackColor = Color::Black;
    }

    Da vielen mir dann die Schuppen von den Augen und ich habe es so geändert:

    	public:
    		Farbdialog(Color HintergrundFarbe, Color RahmenFarbe)
    		{
    			InitializeComponent();
    			//
    			//TODO: Konstruktorcode hier hinzufügen.
    			//
    
    			LinienBreite = 6;
    			pinsel1 = gcnew SolidBrush(RahmenFarbe);
    			malflaeche = panelVorschau->CreateGraphics();
    			panelVorschau->BackColor = HintergrundFarbe;
    
    }

    Da habe ich im Grunde mal wieder viel zu kompliziert gedacht meine ich.

    Lieben Gruß

    lempy

    • Als Antwort markiert lempy Freitag, 7. Februar 2014 10:42
    Freitag, 7. Februar 2014 10:42

Alle Antworten

  • Hallo,

    zum Warum
    Color ist eine Farbe und Brush ein Füllfarbe. Color beschreibt dabei einfach eine Farbe anhand der RGB-Werte. Brush dagegen kann auch noch effekte etc. aufnehmen. Du kannst jederzeit ein Color aus einem SolidBrush erstellen bzw. aus jedem Color einen Brush (wieder Solid). Zum konvertieren siehe Wieso.

    zum Wieso
    Wenn ich mir dein Projekt ansehe, dann finde ich deklarationen wie:

    SolidBrush ^pinsel;

    Du erstellst also eine Füllfarbe. In zeichnePunkte weist du nun die Color-Eigenschaft zu:

    pinsel->Color = spielfeld->BackColor;

    Um nochmal den Unterschied zwischen Farbe und Füllfarbe zu zeigen eine kleine Grafik:

    zum Wie zum Kuckuck
    wir haben vor einiger Zeit mal das Problem geklärt, wie man die Spielfeldgröße hin- und her überträgt. Dazu übergaben wir dem Konstruktor die Infos:

    gcnew einstellungenDialog(...

    Im Konstruktor haben wir damals die übergebene Größe vearbeitet und die RadioButtons "gecheckt". Jetzt müssen wir die übergebene Farbe aber lediglich zwischen speichern. Also musst du eine Variable in der 2. Form anlegen und dieser die Farbe zuweisen:

    Color^ rahmenFarbe;//Dekl. in Klasse
    
    einstellungenDialog(..., Color^ rahmen)
    {
        rahmenFarbe = rahmen;
    }

    Außerdem solltest du in deinem Vorschaubutton o.ä. die übergebene Farbe noch anzeigen:

    buttonRahmen->BackColor = rahmen;

    Beim Aufruf des ColorDialoges musst du nun auch die gewählte Farbe zuweisen:

    ColorDialog^ cd = gcnew ColorDialog();
    cd->Color = BackColor;//Ausgewählte Farbe zuweisen

    Wenn der Aufruf erfolgreich war, gibst du die Farbe neu aus und setzt rahmenfarbe:

    if(cd->ShowDialog() == System::Windows::Forms::DialogResult::OK )
    {
        buttonRahmen->BackColor = cd->Color;//Zum testen im Button ausgeben
        rahmenFarbe = cd->Color;//Variable zuweisen
    }

    Nun muss deine liefereRahmenfarbe-Methode nurnoch die Farbe zurück geben:

    Color liefereRahmenfarbe(){
        return rahmenFarbe;
    }

    Nachdem die Einstellungsdialog wieder geschlossen wurde, kannst du nun die Rahmenfarbe neu setzen:

    rahmenFarbe = neueWerte->liefereRahmenfarbe();

    Die Zeichen-Methoden benutzen dann die neue Farbe. Auch hierzu nochmal eine Grafik:


    Die blauen Pfeile symbolisieren den Gang der Farbe durch die 2 Formen. Die Variable heißt zwar in beiden Formen rahmenFarbe, diese haben aber technisch nichts miteinander gemeinsam, darum unterschiedliche Farben. In Form1 kannst du noch einen Zugriff auf rahmenFarbe sehen. Der orangene Pfeil zeigt, das der Zugriff auf die farbe unabhängig von der Änderung statt findet.

    GDI+ ist in jeder Programmiersprache annähernd gleich. Das Jonglieren mit den ganzen Objekten ist auh übeall annähernd gleich. Der große Vorteil von C# ist allerdings, das man sich oftmals schreibarbeit sparrt, weil VS einem alles vorschlägt was man brauchen könnte.
    Die Grafikverarbeitung ist in keiner Programmiersprache das leichteste und Technologien wie WPF machen zwar vieles einfacher aber auch wieder vieles schwerer.

    PS: Auch direin frohes neues Jahr!


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.


    Freitag, 3. Januar 2014 13:27
  • Hallo Koopakiller

    lieben Dank für Dein unermüdliche Hilfe. Habe mir das ganze noch mal genau angesehen und weis nicht recht ob ich deine Grafik richtig interpretiere.

    1. Die Variable "rahmenFarbe" auf meiner Form1 steht nur für die Form1?

    2. Die Variable "rahmenFarbe" auf der Form2 steht dann nur für die Form2?

    OK. Ist logisch. Sind ja auch im Grunde zwei verschiedene Fenster, die man, wenn man will auch in anderen Programmen verwenden kann. Denke ich.

    3. Dein Punkt "Erstelle Instanz mit übergaben von "rahmenFarbe" auf der Form1 macht mir ein wenig Kopfzerbrechen, weil ich nicht sicher bin wo und was.

    Mein Gedanke dazu ist eine Methode, wie in der Form2 die beiden zur Übergabe nach Form1. (Color liefereBackColor() und Color liefere Rahmenfarbe()) Z. B. Color behalteRahmenfarbe() { return rahmenFarbe;} und das ganze von der Form1 her. Nur wo? In dem Teil, wo die Form2 noch geöffnet ist? Wenn ja, muss ich dafür dann noch eine lokale Color-Variable definieren? Und muss ich bei "einstellungenDialog( this-Width, this->Hight->this->rahmenFarbe) noch einen weiteren Parameter angeben? Das dann auch auf der Form2?

    Naja, werde es erst mal zu versuchen umzusetzen, mir noch mal die Heftchen mit Titeln der OOP ansehen und mich wohl Mitte der Woche noch mal melden. Hoffe zumindest, dass ich das schaffe. Ist nicht immer einfach wenn man Nachts um viere aus den Federn muss. Aber zum Wochenende wird es sicher was.

    Aussicht auf nächstes Thema ist "Arbeiten mit der Registrierung und XML-Dateien". Bin mal gespannt was mich da erwartet. Auf jeden Fall nochmal eine Änderung des Pong.

    Lieben Gruß

    lempy

    Sonntag, 5. Januar 2014 15:11
  • Hallo,
    zu 1. und 2.
    Ja. Die Formen sind auch nur Klassen und jede Variable die du in einer Klasse anlegst gilt nur für die Klasse. Es ist auch richtig, das man aus anderen Programmen die Klassen deiner Anwendung verwenden könnte.

    zu 3.
    Das ist die Zeile

    gcnew einstellungenDialog(...

    Diese ruft den Konstruktor auf. Hier nochmal der kurze Ablauf wie eine Klasse erstellt wird:

    • Deklarieren:
      einstellungenDialog^ einstellungen;
    • zuweisen durch aufruf des Konstruktor:
      einstellungen = gcnew einstellungenDialog(...);
    • Methoden aufrufen bzw. Eigenschaften zuweisen
      einstellungen->WasAuchImmer();
      Für Formen: einstellungen->Show();

    Der Konstruktor ist dabei auch so eine Art Methode. Diese muss man jedoch etwas anders aufrufen (mit gcnew). Deine Idee war nun eine Methode in Form2 zu erstellen, welcher du die Daten übergibst. Das machte ich in dem Beispiel im Konstruktor. Das ist für diesen Fall sogar von Vorteil, da wir vorraussetzen, dass Form2 die jetzigen Farben bekommt. Sonst würden wir eventuell Standardfarben nutzen müssen.

    Wenn du eine weitere Methode zum Datenübertragen aufrufen willst, dann musst du das nach dem Erstellen (nach gcnew) aber vor Show() machen. Sobald du Show() aufrufst, sagst du der Form das diese sich anzeigen soll. Dazwischen muss die Datenübergabe erfolgen.

    Ich empfehle dir auch das Konzept der OOP nochmal näher zu betrachten. Programmieren habe ich auch nicht von Heute auf morgen gelernt und OOP ist nicht das Einfachste.

    PS: Das nächste Thema dürfte etwas einfacher werden. Da ist nicht viel mit verschiedenen Objekten, höchstens noch die Anwendung fertiger Klassen. Dafür sollten die Konzepte der OOP aber beherscht werden.


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    Sonntag, 5. Januar 2014 16:57
  • Lieben Dank!!!

    Bin also für die Abende in dieser Woche voll ausgelastet. Werde mich dann wieder am Wochenende melden.

    Gruß

    lempy

    Sonntag, 5. Januar 2014 17:39
  • Hey Koopakiller

    Bin doch zu blöd, dass zu kapieren  GRRRRR!!!!!!

    In den Lehrheften ist die OOP mit einfachem CLR erklärt und da ist mir alles klar, doch das ganze in Forms um zu setzen ist mir irgendwie zu hoch. Selbst in den bis jetzt erworbenen Büchern ist die OOP nur an Hand von CLR beschrieben. Meine Testversion sieht eher grün aus vom dauernden auskommentieren, weil der Versuch wieder nicht zum Ergebnis kam.

    Ich denke mal das mir das Bilden einer "Instanz" zur Übergabe der Farbe in Form1 Probleme macht. Denn, wenn ich das ganze richtig verstanden haben, dann muss die Form1 ja die ausgewählte Farbe auch wieder an die Form2 zurück geben. Oder nicht?

    Das ist genauso blöd, wie damals Abwicklungen im technischen Zeichnen. Da standen mir auch die Haare zu Berge. Das heißt einen Unterschied gibt es doch, bei den Abwicklungen habe ich wenigstens einen richtigen Ansatz gefunden auf dem ich aufbauen konnte und ich wusste was ich an zu fassen hatte. Hier leider nicht wirklich.

    Deine Anmerkung:

    • Deklarieren:
      einstellungenDialog^ einstellungen;
    • zuweisen durch aufruf des Konstruktor:
      einstellungen = gcnew einstellungenDialog(...);
    • Methoden aufrufen bzw. Eigenschaften zuweisen
      einstellungen->WasAuchImmer();
      Für Formen: einstellungen->Show();

    Ist diese Anmerkung von Dir auf das Öffnen der zweiten Form zurück zu führen, oder wird hier noch mal eine neue Form2 "erstellt"?

    Irgendwie erscheint es mir das OOP mit Forms doch nicht gleich CLR ist. Vor allem dann nicht, wenn man mit zwei Formen arbeitet.

    Meine eigentliche neue Hauptfrage ist, wie bei der Auswahl des gescheckten Radiobutton, wie funktioniert das, dass die neu Farbe auch beim wieder öffnen der Form2 angezeigt wird?

    Meine Gedanken sind im Moment total Wirr und meine Augen bekommen das Schielen, weil nichts auch nur im Ansatz zu funktionieren scheint.

    Gruß

    lempy

    Sonntag, 12. Januar 2014 18:12
  • Die CLR (Common Language Runtime) beschreibt den Teil von .NET der letzten Endes den Code ausführt. Ich nehme darum mal an, das du die Anwendung der Standardklasse soweit verstanden hast, aber es noch beim eigenen Erstelölen der Forms scheitert. Die Programmierung mit .NET Klassen ist überall gleich. Auch Formen halten sich zu 100% an dieses Konzept.

    Ich versuche es nochmal anhand eines anderen Beispiels zu erklären:

    Stelle dir vor, du hast einen Freund. Du verwaltest das Ping-Pong spiel an sich. Der Andere hat aber die Spielregeln (die Einstellungen). Wenn du nun nach anderen Regeln spielen möchtest, musst du zu deinem Freund gehen und dort die neuen Regeln eintragen. Der Freund geht dann mit dir zurück und passt auf, dass du dich auch an die Regeln hälst.
    Du (Form1) schaffst also die Daten zu deinem Freund (Form2) und dieser bringt diese dann zurück (wieder zu Form1).

    Das Übertragen von Daten braucht also immer 2 Beteildigte. Da du nicht so recht voran zu kommen scheinst, schlage ich dir vor ein ganz einfaches Beispiel zu erstellen, welches in einer Konsole, also ohne Formen arbeitet.

    Nachfolgend mal ein kleiner Plan. Du kannst mir deinen Fortschritt gerne hier posten, dann gucke ich mir den an und korrigiere diesen.

    1. Erstelle eine Klasse Klasse1, welche eine Variable (MeinWert) vom Typ int besitzt.
    2. Erstelle eine 2. Klasse Aendern. Diese hat ebenfalls eine Variable MeinWert vom Typ int.
    3. Diese Klasse hat 2 Methoden: SetzeWert und LeseWert
      Diese setzen bzw. lesen den Wert der Variablen MeinWert in Aendern.
    4. Nun erstellst du eine Methode in Aendern, welche FrageBenutzer heißt. Diese ruft einen Wert vom Benutzer ab und speichert diesen in MeinWert. Folgende Zeile liest die Infos vom Benutzer und weißt diese zu:
      MeinWert = int::Parse(Console::ReadLine());
    5. Nun rufst du aus Klasse 1 die SetzeWert-Methode auf und übergibst ihr MeinWert.
      Anschließend rufst duFrageBenutzer auf.
      Nun rufst du MeinWert aus Aendern wieder ab, indem du LeseWert aufrufst.
      Wo die Aufrufe statt finden ist egal, sie müssen nur hintereinander weg ablaufen.

    Im Grunde ist das genau das selbe wie mit den Formen, nur ohne dem Teilweise verwirrenden GUI-Programmieren.

    Den Rest würde ich danach nochmal versuchen zu erklären. Das Beispiel könnte mir schon viel Arbeit abnehmen ;)

    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    Sonntag, 12. Januar 2014 19:44
  • Hey

    Werde mich mal daran machen und die Abende damit verbringen. Melde mich dann am Wochenende wieder

    Lieben Dank

    lempy

    Montag, 13. Januar 2014 15:58
  • Hallo Koopakiller

    Hat leider doch etwas länger gedauert als gedacht. Habe versucht Deine Anweisungen in zwei Varianten zu erstellen.

    1. Variante

    Ich habe im Menü den Punkt Projekt -> Klasse hinzufügen gewählt. Das für beide Klassen. Bis zum Aufruf der Klasse Aendern für die Eingabe lief es. Aber dann die Klasse Aendern in der Klasse1 aufzurufen schlägt bei mir fehl. Sprich nach einigen Versuchen muss ich gestehen, keine Ahnung wie das funktioniert. Klasse in Klasse aufrufen habe ich bis jetzt nicht in meinen Büchern gefunden oder wenn doch, dann kann ich das nicht umsetzen. Die Klassen habe ich in der Datei stdafx.h includiert.

    2. Variant ist diese:

    // TomTest1.cpp: Hauptprojektdatei.
    
    #include "stdafx.h"
    
    using namespace System;
    
    ref class Aendern 
    {
    	Int32 MeinWert;
    
    public:
    
    	Int32 setzeWert(Int32 WertNeu)
    	{
    		WertNeu = MeinWert;
    		return MeinWert;
    	}
    
    	Void leseWert()
    	{
    		/*MeinWert = Convert::ToString();*/
    		Console::Write("{0}",MeinWert);
    	}
    	
    	Void FrageBenutzer()
    	{
    		Console::WriteLine("Bitte in Funktion \"FrageBenutzer\" der Klasse \"Ändern\" eine Zahl eingeben.\n");
    		
    		MeinWert = Console::Read();
    
    		Console::WriteLine();
    
    		leseWert();
    
    		Console::WriteLine();
    	}
    };
    
    ref class Klasse1
    {
    	Int32 MeinWert;
    	
    public:
    	
    	Void aufruf()
    	{
    		Console::WriteLine("Aus Klass \"Klasse1\"\n");
    		Aendern ^test1 = gcnew Aendern();
    		MeinWert = test1->setzeWert(MeinWert);
    		test1->leseWert();
    		Console::WriteLine();
    		
    	}
    
    	/*Void ausgeben()
    	{
    		Aendern ^test1 = gcnew Aendern();
    		test1->leseWert();
    		Console::WriteLine();
    	}*/
    
    };
    
    int main(array<System::String ^> ^args)
    {
    	Aendern ^test1 = gcnew Aendern();
    	
    	test1->FrageBenutzer();
    
    	Console::WriteLine();
    
    	Klasse1 ^test2 = gcnew Klasse1();
    	
    	test2->aufruf();
    	/*test2->ausgeben();*/
    
    	Console::WriteLine();
    
    	Console::Read();
    
    	return 0;
    }
    

    Diese Version läßt sich zwar compilieren, aber übergibt nicht den eingegebenen Wert. Ich habe nicht die leiseste Ahnung warum nicht.

    Im Übrigen muss ich sagen, war das in C++/CLR zu erstellen gar nicht so einfach nach so langer Zeit.

    Lieber Gruß

    lempy

    Dienstag, 21. Januar 2014 17:56
  • Hallo,
    Das Projekt mit den 2 Klassen ist genau das Selbe, wie mit den 2 Formen. Ich kann nur nicht genau sagen, wo es wahrscheinlich den zu lösenden Knoten gibt. So schlecht sehen deine Klassen nämlich garnicht aus. Hier erstmal die Fehlerkorrekturen:

    1. MeinWert in Klasse1 sollte ebenfalls public sein. Das dient aber mehr zum setzen von außerhalb, als dem Wert übergeben.
    2. In main brauchst du keine Instanz von Aendern. Hier soll wirklich nur Klasse1 benutzt werden:
      Klasse1^ test = gcnew Klasse1();
      test->MeinWert = 12;//Standardwert
      Console::WriteLine(test->MeinWert);//Ausgabe des gesetzten Werts
      test->aufruf(); //<- wichtigster Teil
      Console::WriteLine(test->MeinWert);//Nochmalige Ausgabe des Werts (diemal der neue, vom Benutzer festgelegte)
      Console::ReadKey();
    3. Aendern.FrageBenutzer muss natürlich auch aufgerufen werden. Also muss die Klasse1.aufruf-Methode abgeändert werden:
      Void aufruf()
      {
      	Console::WriteLine("Aus Klass \"Klasse1\"\n");
      	Aendern ^test1 = gcnew Aendern();
      	MeinWert = test1->setzeWert(MeinWert);
      	test1->FrageBenutzer();
      	test1->leseWert();
      	Console::WriteLine();
      }
    4. Ich weiß nicht, wie vertraut du mit der Konsolenprogrammierung bist. Ein Int32 ließt man so ein:
      MeinWert = Int32::Parse(Console::ReadLine());
    5. setzeWert und leseWert sind auch nicht ganz korrekt. setzeWert muss MeinWert zuweisen. leseWert muss MeinWert zurück geben:
      Void setzeWert(Int32 WertNeu)
      {
      	MeinWert = WertNeu;
      }
      
      Int32 leseWert()
      {
      	return MeinWert;
      }
    6. In FrageBenutzer solltest du noch den momentanen Wert ausgeben:
      Void FrageBenutzer()
      {
      	Console::WriteLine("Aktueller Wert: " + MeinWert);

    Die Fehler sehen jetzt vielleicht viel aus, aber die Grundstruktur waren auf jeden Fall da.

    Ich versuchs nochmal zu erklären, welcher Code hier was macht. Im Grunde ist es das Selbe, wie in meiner 2. Grafik.

    • Klasse1
      Enthält einfach die Informationen, welche du speichern möchtest. Hier ist es nur ein einziger Int32-Wert.
    • Klasse1.aufruf
      Der Aufruf entspricht dem Moment, wenn in der Hauptform auf den Einstellungen-Button (/Menü) klickt.
    • Aendern
      Diese Klasse ist nichts anderes als Form2. Sie ruft Informationen vom Benutzer ab und setzt diese entsprechend.
    • Aendern.setzeWert
      Hier wird der Wert von Klasse1 an Aendern übergeben. Somit kann der momentan festgelegte Wert ausgegeben werden (In FrageBenutzer, siehe Punkt 6)
    • Aendern.FrageBenutzer
      Diese Methode Fragt den Benutzer nach einem neuen Wert. Dieser wird dann einfach in MeinWert abgelegt.
    • Aendern.leseWert
      Hier kann Klasse1 den eventuell neu gesetzten Wert wieder auslesen.

    Vielleicht scheitert es auch am Konzept des Austausch. In dem Fall hilft es dir vielleicht nochmal andere Seiten zu lesen. Dabei sei aber gleich gesagt, das es sich mehr lohnt nach C#-Beispielen zu suchen. Für C++/CLI wirst du kaum etwas bis nichts finden.

    Fragen zu meinem Beispiel kannst du natürlich jederzeit stellen.

    Im Übrigen muss ich sagen, war das in C++/CLR zu erstellen gar nicht so einfach nach so langer Zeit.

    Das kenne ich. Da deine Fragen momentan das einzige sind, wofür ich C++/CLI benötige, ist es schwierig den Code ohne Syntaxfehler zu schreiben ;)


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    Mittwoch, 22. Januar 2014 21:41
  • Hallo Koopakiller

    Von der "Funktion" oder "Methode" Parse() habe ich in meinen Lehrheften nichts erfahren und in meinen Büchern ist es auch nur in einem aufgelistet mit der Bemerkung: "Das es ein/e BigInteger-Methode ist, die Strings und Int32 und Konsorten in den benötigten Variablentyp umwandelt." Kurz gesagt: Bis Dato kannte ich diese Methode nicht. Bin Deinem Link gefolgt und habe ein paar interessante Seiten gefunden, aber leider noch nicht den Aha-Moment.

    Noch mal zu meinem Problem ein paar Fragen um die Stellen heraus zu filtern, an denen es hakt?

    1. Klasse1 = Mein Haupform? (Enthält die einfache variable "Color rahmenFarbe" in public)

    2. Klasse1.Aufruf =

                                einstellungenDialog3 ^neueWerte =

                                gcnew einstellungenDialog3(this->Width, this->Height, this->rahmenFarbe);

    3. Aendern = Meine Form2 (einstellungenDialog). Sie setzt die Einstellungen in ihrer Form

                        (die Vorschau) und danach das Programm in die neuen Farben.

    4. Aendern.setzeWert = ???? Würde das mit meiner geänderten Methode

    Color liefereRahmenColor(Color rahmen)
    		{
    			rahmen = rahmenFarbe;
    			return rahmenFarbe;
    		}

    gleich zu setzen sein? Oder währe das eher leseWert? Oder muss diese Methode von Grund auf neu definiert werden in der Form2?

    5. Aendern.FrageBenutzer = ????? Kann dafür auch die Parse() Methoden verwand werden? Oder muss ich dafür

                                               eventuell eine neue ColorDialog() Methode aufrufen?

    6. Aendern.leseWert = ?????? Mit Console::WriteLine()? Ich denke eher nicht. Mir fallen da nur die Methoden

                                      Get() und Set() ein. Das dürften aber die Methode leseWert() und setzeWert() sein.

    Wo muss ich die noch nicht ganz fertige Methode

    Void aufruf()
    		{
    			einstellungenDialog ^test1 = gcnew einstellungenDialog();
    
    			rahmenFarbe = test1->lieferRahmenColor(rahmenFarbe);
    		
    			/*test1->liefereRahmenColor(rahmenFarbe);*/
    			pinsel->Color = rahmenFarbe;
    		}

    in der Form1 einfügen und zwar als public? In den eigen etstellten Methoden (im Konstruktor) oder gleich nach

    einstellungenDialog3 ^neueWerte =

    gcnew einstellungenDialog3(this->Width, this->Height, this->rahmenFarbe);

    Zietat: So schlecht sehen Deine Klassen nicht aus.

    Ist in CLR irgendwie einfacher durch zu blicken. Denke es liegt daran, das der Code vollständig selbst erstellt wird und C++ nicht "automatisch" irgendwas dazu schreibt wie in Forms.

    Die Umsetzung in Forms fällt mir verdammt schwer. Na ja, vielleicht finden wir jetzt die Stelle  wo es mir schwer fällt das ganze um zu setzen.

    Lieben Gruß

    lempy

    einstellungenDialog3 ^neueWerte =

    gcnew einstellungenDialog3(this->Width, this->Height, this->rahmenFarbe);


    • Bearbeitet lempy Donnerstag, 23. Januar 2014 16:46 Was vergessen
    Donnerstag, 23. Januar 2014 16:44
  • Hallo,
    Viele Datentypen (Int32, Double, Decimal und auch BigInteger) haben eine Parse-Methode. diese erstellt eine Instanz des Typs aus einem String.

    zu 1.
    Genau.

    zu 2.
    Der Code ist der Aufruf von Aendern. In der Methode aufrufen.

    zu 3.
    Im Spiel werden die Farben dann wieder von Form1 gesetzt. Der Rest stimmt soweit.

    zu 4.
    Die Methode macht wenig Sinn. Es gibt 2, wie du bei 6. richtig erkannt hast:

    Methode: Get
    setzeWert
    Set
    leseWert
    Parameter
    keine
    Da der Wert abgerufen werden soll.  
    Den zu setzenden Wert  
    Rückgabewert  
    Den in der Klasse gespeiherten Wert.  
    keiner
    Da wir den Wert setzenwollen.  

    Beide zusammen entsprechen einer Eigenschaft mit Getter und Setter. Du brauchst also 2 Methoden.

    zu 5.
    FrageBenutzer entspricht dem Moment, in dem du die 2. Form anzeigst und dieser etwas ändern kann. Der Aufruf von Parse muss in dieser Methode statt finden. In der 2. Form müsstest du dann den ColorDialog erst im Button-Click anzeigen.

    zu 6.
    WriteLine() dient hier nur zum ausgeben des Werts. Für mehr ist es hier nicht zu gebrauchen. Zum Rest siehe: zu 4.

    aufruf enthält nur den Code, der beim aufrufen des Einstellungsdialoges aufgerufen wird. Also im Click-Handler des Menüitems. In dem Konsolenbeispiel brauchten wir einfach einen Ersatz dafür.

    Ist in CLR irgendwie einfacher durch zu blicken. Denke es liegt daran, das der Code vollständig selbst erstellt wird und C++ nicht "automatisch" irgendwas dazu schreibt wie in Forms.

    Die Umsetzung in Forms fällt mir verdammt schwer. Na ja, vielleicht finden wir jetzt die Stelle  wo es mir schwer fällt das ganze um zu setzen.

    Das ist wohl einer der Nachteile beim Fensterprogrammieren mit C++/CLI. Das wirkt alles unübersichtlich. Wenn du dir deine Form-Klasse ansiehst, hast du keinen viel anderen Code als den, der auch in Klasse1 und Aendern vorkommt.

    Du hast die Methode InitializeComponent. Diese kannst du einfach ignorieren (diese erzeugt das Design der Form). Sonst findest du noch den De- und Konstruktor und natürlich die Variablen für die Buttons etc.
    Was übrig bleibt, sind die Klassen, wie sie im Konsolenbeispiel existieren.

    Das Konzept

    • Gebe gespeicherten Wert an Einstellungs-Form
    • Rufe Einstellungs-Form auf
      > Lasse den Benutzer einen neuen Wert auswählen
    • Rufe den Wert aus der Einstellungsform ab
    • Zeichne Spielfeld neu

    hast du, denke ich verstanden. Jetzt geht es nur darum den Code auch wirklich in die beiden Form-Klassen einzufügen.

    PS: Zur Begrifflichkeit
    CLR meint Common Language Runtime, damit wird der .NET Code ausgeführt. Dein Code wird, wenn überhaupt, von Visual Studio ergänzt. C++-Standards schreiben die Syntax vor. Das CLI im Namen steht für die Verwendung von .NET - und nicht Fenster-Anwendungen sind meistens Konsolen ;)


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    Donnerstag, 23. Januar 2014 17:23
  • Hallo Koopakiller

    So langsam bin ich wirklich am verzweifeln.

    Fragen zu Deinen Punkten:

    Zu Deinem Punkt 3: Im Spiel werden die Farben dann wieder von Form1 gesetzt

    Gans konkret. Ich muss auf der Form1 zwei Methoden erstellen z. B. setzeWert() und leseWert()? Werden die als Methoden in der publicrubrik erstellell und dann nach "einstellungenDialog3 ^neueWerte = gcnew einstellulngenDialog3(this->Width, this->Height, this->rahmenFarbe)" aufgerufen?

    Wenn ich das ganze so ansehe, dann habe ich doch die Get- und Set-Methode in Form2 mit den Anweisungen

    Set()

    Color setzeFarbe(Color NeueFarbe)
    {
    	NeueFarbe = rahmenFarbe;
    	return rahmenFarbe;
    
    }
    Get()
    Color liefereRahmenColor(Color rahmen)
    
    {
    return rahmenFarbe;
    
    }
    

    Menüpunkt: Einstellulngen->Spielfeld. Etwas abgeändert aber funktioniert so.

    einstellungenDialog3 ^neueWerte = gcnew einstellungenDialog3(this->Width, this->Height, this->rahmenFarbe);
    
    if (neueWerte -> ShowDialog() == Windows::Forms::DialogResult::OK)
    			 {
    				 // die neue Größe holen
    
    				 neueGroesse = neueWerte -> liefereWert();
    				 spielfeld->BackColor = neueWerte->liefereBackColor();
    				 rahmenFarbe = neueWerte->liefereRahmenColor();
    
     neueWerte -> Close();
    
    // das Formular ändern
    
    				 this -> Width = neueGroesse.X;
    				 this -> Height = neueGroesse.Y;
    
    				 // neu ausrichten
    
    				 // bitte jeweils in einer Zeile eingeben
    
    				 this -> Left = (Screen::PrimaryScreen -> Bounds.Width - this -> Width) / 2;
    				 this -> Top = (Screen::PrimaryScreen -> Bounds.Height - this -> Height) / 2;
    
    // die Zeichenfläche neu beschaffen
    
    				 zeichenflaeche = spielfeld -> CreateGraphics();
    
    				 // das Spielfeld neu setzen
    
    				 setzeSpielfeld();
    
    				 // Spielfeld löschen
    
    				 zeichenflaeche -> Clear(spielfeld -> BackColor);
    
    // und einen neuen Ball und Schläger zeichnen
    
    				 neuerBall();
    
    }
    			 this->zeichneSpielfeld();
    			 this->zeichnePunkte();
    };

    Wie Du siehst: Die Übergabe zu Form1 funktioniert, aber die Vorschau behält beim Wiederaufruf die Einstellung nicht.

    Ich denke, wenn die neue Farbe in Form2 gesetzt ist, dann bleibt sie erhalten. Doch leider ist das nicht so

    und wenn ich die selben Methoden in der Form1 schreiben würde, dann kann ich doch aber von der Form2 aus nicht darauf zu greifen, weil Form2 Form1 nicht kennt. Trotz der Einbindung in stdafx.h. Da bekomme ich einfach

    keine Parallele zu CLR. Einfach zum Mäusemelken.

    Lieben, lieben Dank für Deine Geduld

    lempy

    Freitag, 24. Januar 2014 15:07
  • Hallo,
    ich antworte erst jetzt, weil ich nochmal überlegte woran es scheitert. Aber mir sind wirklich die Ideen ausgegangen.

    Die Get- und Set-Methoden in Form2 sind richtig (ok, Set braucht eigentlich keinen Rückgabewert). In Form1 brauchst du keine Methoden wie diese.

    Du musst natürlich vor dem Aufruf von ShowDialog() noch die Set-Methoden aufrufen bzw. die übergebenen Daten im Konstruktor verarbeiten.

    Die Fare bleibt in Form2 nicht erhalten, da du eine neue Instanz erstellt (gcnew).

    Form1 ist zuständig sich die neuen Werte zu hohlen (get...) bzw. die alten zu übergeben (set... bzw. Konstruktor). Form2 kennt Form1 am besten garnicht.

    Ich weiß leider nicht, wie ich noch etwas erklären kann. Ich sehe natürlich die Parallelen zur Konsole, ich kann es aber auf keinem anderen Weg erklären.


    Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    Montag, 27. Januar 2014 17:24
  • Hey Koopakiller

    Habe das Rätzel gelöst!!!!! Dank eines anderen Forums, wo mir jemand mitgeteilt hat, dass die Farbe schon da ist auf der Form2. Nur ich würde nichts damit tun. Nach einigem Hin und Her hat er mir dieses Codefragment gezeigt:

    Farbdialog(Color HintergrundFarbe, Color RahmenFarbe)
    {
    	InitializeComponent();
    	//
    	//TODO: Konstruktorcode hier hinzufügen.
    	//
    	LinienBreite = 6;
    	pinsel1 = gcnew SolidBrush(Color::White);
    	malflaeche = panelVorschau->CreateGraphics();
    	panelVorschau->BackColor = Color::Black;
    }

    Da vielen mir dann die Schuppen von den Augen und ich habe es so geändert:

    	public:
    		Farbdialog(Color HintergrundFarbe, Color RahmenFarbe)
    		{
    			InitializeComponent();
    			//
    			//TODO: Konstruktorcode hier hinzufügen.
    			//
    
    			LinienBreite = 6;
    			pinsel1 = gcnew SolidBrush(RahmenFarbe);
    			malflaeche = panelVorschau->CreateGraphics();
    			panelVorschau->BackColor = HintergrundFarbe;
    
    }

    Da habe ich im Grunde mal wieder viel zu kompliziert gedacht meine ich.

    Lieben Gruß

    lempy

    • Als Antwort markiert lempy Freitag, 7. Februar 2014 10:42
    Freitag, 7. Februar 2014 10:42