Zeiger auf Form1 an Form2 übergeben?



  • Hallo Leute,
    erstmal nettes Forum 👍 . Jetzt zu meinem Problem: Hab zwei Forms, also zwei Klassen Form1 in Form1.h und Form2 in Form2.h. Estell jetzt in Form1.h mit:

    Form2^ form2 = gcnew Form2(this);
    form2->Show();
    

    ein neues Objekt. Dazu habe ich die Form2.h in der Form1.h includet. Geht auch super! Möchte mit this einen Zeiger auf Form1 übergeben.
    In Form2.h mein Konstruktor und die Deklaration von fm1:

    public: Form2(Form1^ fm)
    	{
    	  InitializeComponent();
    	  //
    	  //TODO: Konstruktorcode hier hinzufügen.
    	  //
    	  fm1 = fm;
    	}
    
    public: Form1^ fm1;
    

    Jetzt meckert der Compiler das Form1 nicht definiert ist, ist mir schon klar, aber ein #include "Form1.h" bringt auch nichts. Was muss ich machen?
    Hab auch schon die tuts hier gelesen, komm aber nicht weiter. Verwende VS 2005 PE
    Danke



  • => FAQ



  • Ja die hab ich mir schon angeschaut, aber hab nicht direkt gefunden was ich machen muss. Ausser das man den anderen Weg gehen kann:

    Form2 ^f2 = gcnew Form2(this);
    f2->ShowDialog();
    this->label1->Text = f2->ErgebnisFuerLabel1;
    

    Mit vorwärtsdeklaration gehts auch nicht. Muss doch nur ne Kleinigkeit sein!



  • So geht es auch nicht:
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-165614-and-highlight-is-form+zeiger.html

    Er kennt einfach das Form1 in der Form2 nicht. Es kommt immer:
    Fehler 1 error C2065: 'Form1': nichtdeklarierter Bezeichner

    Kann denn keiner was dazu sagen. Probier schon seit mehreren Stunden das zu lösen



  • Hab jetzt selber eine "Lösung" gefunden. Wenn man in der Form2.cpp die Form1.h includet kann man dort z.B. Form1^ fm ohne Probleme deklarieren.
    Aber wieso geht das nicht einfach in der Form2.h?????????????? 🙄 🙄 🙄 🙄
    Kommt immer:
    Fehler 1 error C2065: 'Form1': nichtdeklarierter Bezeichner
    Wo muss man die Form1.h includen damit ich auch in der Form2.h daraufzugreifen kann?



  • Die Lösung findest Du im Grundlagenbuch und bei der Suche nach dem Begriff Forwärtsdeklarationen. Lernarbeit nimmt Dir keiner ab. Es gab hier auch schon viele Beiträge zu diesem Thema.



  • Hab zwaz voher schon geschrieben, dass es mit einer Vortwärtsdeklaration auch nicht geht, aber hier mal der Code mit Vorwärtsdeklaration:
    Form1.h.

    #pragma once
    
    #include "Form2.h"
    
    namespace test {
    
    	using namespace System;
    	using namespace System::ComponentModel;
    	using namespace System::Collections;
    	using namespace System::Windows::Forms;
    	using namespace System::Data;
    	using namespace System::Drawing;
    
    	/// <summary>
    	/// Zusammenfassung für Form1
    	///
    	/// Warnung: Wenn Sie den Namen dieser Klasse ändern, müssen Sie auch
    	///          die Ressourcendateiname-Eigenschaft für das Tool zur Kompilierung verwalteter Ressourcen ändern,
    	///          das allen RESX-Dateien zugewiesen ist, von denen diese Klasse abhängt.
    	///          Anderenfalls können die Designer nicht korrekt mit den lokalisierten Ressourcen
    	///          arbeiten, die diesem Formular zugewiesen sind.
    	/// </summary>
    
    	public ref class Form1 : public System::Windows::Forms::Form
    	{
    	public:
    		Form1(void)
    		{
    			InitializeComponent();
    			//
    			//TODO: Konstruktorcode hier hinzufügen.
    			//
    		}
    
    	protected:
    		/// <summary>
    		/// Verwendete Ressourcen bereinigen.
    		/// </summary>
    		~Form1()
    		{
    			if (components)
    			{
    				delete components;
    			}
    		}
    	public: System::Windows::Forms::Button^  button1;
    	protected: 
    
    	private:
    		/// <summary>
    		/// Erforderliche Designervariable.
    		/// </summary>
    		System::ComponentModel::Container ^components;
    
    #pragma region Windows Form Designer generated code
    		/// <summary>
    		/// Erforderliche Methode für die Designerunterstützung.
    		/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
    		/// </summary>
    		void InitializeComponent(void)
    		{
    			this->button1 = (gcnew System::Windows::Forms::Button());
    			this->SuspendLayout();
    			// 
    			// button1
    			// 
    			this->button1->Location = System::Drawing::Point(128, 114);
    			this->button1->Name = L"button1";
    			this->button1->Size = System::Drawing::Size(78, 50);
    			this->button1->TabIndex = 0;
    			this->button1->Text = L"button1";
    			this->button1->UseVisualStyleBackColor = true;
    			this->button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
    			// 
    			// Form1
    			// 
    			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
    			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
    			this->ClientSize = System::Drawing::Size(284, 264);
    			this->Controls->Add(this->button1);
    			this->Name = L"Form1";
    			this->Text = L"Form1";
    			this->ResumeLayout(false);
    
    		}
    #pragma endregion
    	private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {
    				 Form2^ fm2 = gcnew Form2;
    				 fm2->Show(this);
    			 }
    	};
    }
    

    Und Form2.h:

    #pragma once
    
    using namespace System;
    using namespace System::ComponentModel;
    using namespace System::Collections;
    using namespace System::Windows::Forms;
    using namespace System::Data;
    using namespace System::Drawing;
    
    namespace test {
    
    	/// <summary>
    	/// Zusammenfassung für Form2
    	///
    	/// Warnung: Wenn Sie den Namen dieser Klasse ändern, müssen Sie auch
    	///          die Ressourcendateiname-Eigenschaft für das Tool zur Kompilierung verwalteter Ressourcen ändern,
    	///          das allen RESX-Dateien zugewiesen ist, von denen diese Klasse abhängt.
    	///          Anderenfalls können die Designer nicht korrekt mit den lokalisierten Ressourcen
    	///          arbeiten, die diesem Formular zugewiesen sind.
    	/// </summary>
    
    	ref class Form1;
    
    	public ref class Form2 : public System::Windows::Forms::Form
    	{
    	public:
    		Form2(Form1^ fm)
    		{
    			InitializeComponent();
    			//
    			//TODO: Konstruktorcode hier hinzufügen.
    			//
    			fmzeiger = fm;
    		}
    
    	protected:
    		/// <summary>
    		/// Verwendete Ressourcen bereinigen.
    		/// </summary>
    		~Form2()
    		{
    			if (components)
    			{
    				delete components;
    			}
    		}
    	private: System::Windows::Forms::Button^  button1;
    	public: Form1^ fmzeiger;
    	protected: 
    
    	private:
    		/// <summary>
    		/// Erforderliche Designervariable.
    		/// </summary>
    		System::ComponentModel::Container ^components;
    
    #pragma region Windows Form Designer generated code
    		/// <summary>
    		/// Erforderliche Methode für die Designerunterstützung.
    		/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
    		/// </summary>
    		void InitializeComponent(void)
    		{
    			this->button1 = (gcnew System::Windows::Forms::Button());
    			this->SuspendLayout();
    			// 
    			// button1
    			// 
    			this->button1->Location = System::Drawing::Point(131, 120);
    			this->button1->Name = L"button1";
    			this->button1->Size = System::Drawing::Size(74, 48);
    			this->button1->TabIndex = 0;
    			this->button1->Text = L"button1";
    			this->button1->UseVisualStyleBackColor = true;
    			this->button1->Click += gcnew System::EventHandler(this, &Form2::button1_Click);
    			// 
    			// Form2
    			// 
    			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
    			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
    			this->ClientSize = System::Drawing::Size(284, 264);
    			this->Controls->Add(this->button1);
    			this->Name = L"Form2";
    			this->Text = L"Form2";
    			this->ResumeLayout(false);
    
    		}
    #pragma endregion
    	private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e)
    			 {
    				 fmzeiger->Button1->Text = ""; //Hier der Fehler
    			 }
    	};
    }
    

    Fehler: error C2027: Verwendung des undefinierten Typs "test::Form1"

    Also mit einer Vorwärtdeklaration kann man doch nicht auf die Methoden einer Klasse zugreifen, oder doch? 😡



  • Wie gesagt, beschäftige Dich mal ernsthaft mit Vorwärtsdeklaration, such mal im Forum und beschäftige Dich mal mit der Trennung von Definition und Deklaration.

    Es ist zwar ein wenig Arbeit, aber das Wissen ist unumgänglich und selbst erarbeitet Wertvoll. Die Frage von Dir zeigt aber zumindest, das Du Dich noch nicht wirklich damit beschäftigt hast.



  • Also hab keine Ahnung was du meinst wie es gehen könnte. Vielleicht geht es ja so nicht wie ich mir es vorstelle. Kenne zwar die drei anderen Möglichkeiten um auf das gleiche Ergebniss zu kommen, aber so gehts wohl nicht!

    Falls du mit Trennung von Definition und Deklaration meinst das ich die Definition des Button Click Ereignisses in der h datei mach und die Deklaration in der cpp, das kenn ich schon. Da kann ich dann auf meinen Form1 Pointer zugreifen. Aber ich möchte ja nur wissen ob das auch alles nur im Header geht, also ohne etwas in die cpp Datei zu schreiben?

    Danke



  • Hi,

    ich suche jetzt schon seit 2 Tagen etliche Stunden, habe aber noch keine Lösung gefunden.

    Man kann eigentlich als beispiel den Quelltext von mrmiagi0101 nehmen.
    Ich habe es jetzt endlich hinbekommen, dass keine Compiler-Fehler mehr kommen, indem ich:

    #include "stdafx.h"
    #include "Form2.h"
    #include "Form1.h"
    using namespace test9;
    
    System::Void test9::Form2::button1_Click(System::Object^  sender, System::EventArgs^  e)
    		 {
    			 Form1^ f = (Form1^)this->Owner; /* CForm1-Objekt*/
    			 f->label1->Text = this->textBox1->Text;
    }
    
    System::Void test9::Form2::button2_Click(System::Object ^  sender, System::EventArgs ^  e)
    {
    	Form1^ f = (Form1^)this->Owner; /* CForm1-Objekt*/
    	f->label2->Text = this->textBox1->Text;
    }
    

    in die Cpp des Form2 gesteckt habe.

    Mein momentanes Problem besteht aber dadrin, dass jetzt Linker error kommen. Ich kann keine Cpps benutzen und bin gezwungen den kompletten Code in der .h zu schreiben.
    Ich wäre sehr dankbar wenn mir jemand einen Tipp geben könnte, wie ich das in der .h zum laufen bekomme.

    Danke



  • Hallo,

    Ich habe es jetzt endlich hinbekommen, dass keine Compiler-Fehler mehr kommen, indem ich:

    [...]

    in die Cpp des Form2 gesteckt habe

    So ist es auch richtig(er).

    Mein momentanes Problem besteht aber dadrin, dass jetzt Linker error kommen.

    Welche?

    Ich kann keine Cpps benutzen und bin gezwungen den kompletten Code in der .h zu schreiben.

    Dann wirst du diese .h-Datei nur genau einmal in irgend einer anderen .cpp-Datei includieren dürfen, denn sonst gibt es Mehrfach-Definitions-Fehler.

    MfG,

    Probe-Nutzer



  • Welche?

    Uf, dafür muss ich ein klein wenig ausholen.

    Also ich schreibe gerade mit einem Freund einen Raytracer. In Form1 wird das Bild gerendert weshalb in dieser die "Raytracer.h" includiert ist.
    Dann habe ich noch die ObjectManagement Form von der aus ich Objekte hinzufügen bzw verändern möchte.
    Includes in Form1:

    #include "Raytracer.h"
    
    #include <stdlib.h>
    #include <windows.h>
    #include "ObjectManagement.h"
    

    So, wie schon geschrieben habe ich jetzt bei der ObjectManagement-Form eine Cpp erstellt in der "Form1.h" includiert wird.

    #include "stdafx.h"
    
    #include "Form1.h"
    
    #include "ObjectManagement.h"
    using namespace RaytracingForm;
    
    void RaytracingForm::ObjectManagement::test()
    {
    	Form1^ rayform = (Form1^)this->Owner;
    	rayform->CloseForm2();			
    }
    

    Wenn ich das jetzt so debugge kommen folgende Fehler:

    1>RaytracingForm.obj : error LNK2005: "public: __clrcall Raytracing::Objects::Object::~Object(void)" (??1Object@Objects@Raytracing@@$$FQAM@XZ) ist bereits in ObjectManagement.obj definiert.
    1>RaytracingForm.obj : error LNK2005: "public: virtual class Raytracing::Objects::Intersectinfo * __clrcall Raytracing::Objects::Kugel::Intersect(class Raytracing::Ray,class Raytracing::Objects::Object *,double)" (?Intersect@Kugel@Objects@Raytracing@@$$FUAMPAVIntersectinfo@23@VRay@3@PAVObject@23@N@Z) ist bereits in ObjectManagement.obj definiert.

    Und noch etliche andere LNK2005. Anscheinend für fast alle Funktionen von Klassen in meinem Raytracer.
    Ich habe mich schon über die Fehler erkundigt, doch komme ich da auch zu keinem Ergebnis.
    Danke für alle weitere Hilfe





  • Hmmm, ok
    habe das Problem verstanden, verstehe aber nicht, warum es bei mir auftritt.
    Habe schon einen Versuch gemacht:

    Ich habe in der "Raytracer.h" eine Klasse:

    class Raytracer
    {
    public:
    void InitScene();
    }
    

    und dann weiter unten den Quelltext für InitScene:

    void Raytracer::InitScene()
    {
        //tue was
    }
    

    Wenn ich das so mache, dann kommt für die Funktion ein Linker-Fehler.
    Das könnte ich beheben, indem ich den Code mit in die Klasse nehme:

    class Raytracer
    public:
    void InitScene()
    {
        //tue was
    };
    

    Dann ist der weg.
    Aber bei einem Programm mit über 3000 Zeilen Code wird das sehr unübersichtlich und das ist ja auch nicht wie Klassen eigentlich aufgebaut sein sollten.
    Also die Frage:
    Wie kann ich die Linker-Errors noch beheben? Wieso tauchen sie überhaupt auf?(Ich sehe keinen Verstoß gegen die ODR)



  • Wenn Du die eine .h-Datei in zwei verschiedenen .cpp-Dateien includierst, wird die Funktion InitScene zweimal übersetzt. Der Linker weiss dann nicht, welche er nehmen soll und meldet den Fehler.

    Mal ne ganz blöde Frage: Warum (zum Geier) solltest Du gezwungen sein, den Code komplett in .h-Dateien zu schreiben?!



  • Ich weiß auch nicht mehr genau warum. Ich glaube da tauchten auch Linker-Fehler auf, wo wir uns dann so beholfen haben.

    Aber wie ich das Problem lösen kann mir keiner Veraten? Wäre echt schade, dann müsste ich mein Programm ein klein wenig umgstallten und es wäre bei weitem nicht so User-Freundlich.



  • Aber wie ich das Problem lösen kann mir keiner Veraten?

    Grundlagenbuch raus und erst mal ein paar Consolenprograme geschrieben.



  • Also ich glaube kaum, dass mir das weiterhelfen würde. Habe schon etliche Consolenprogramme geschrieben (Schätzung so um die 30-50). Darunter auch komplexere wie Schiffeversenken mit über 2000 Zeilen Code, wo ich nie solche Fehler hatte.

    Wenn es was mit Grundlagen zu tun hat, dann stehe ich seit zwei Tagen auf dem Schlauch, und es wäre schön wenn mich doch einer Aufklären könnte.



  • Hat sich erledigt.

    Danke für Denkanstöße.



  • swexel schrieb:

    Also ich glaube kaum, dass mir das weiterhelfen würde. Habe schon etliche Consolenprogramme geschrieben (Schätzung so um die 30-50). Darunter auch komplexere wie Schiffeversenken mit über 2000 Zeilen Code, wo ich nie solche Fehler hatte.

    Scheint wohl irgendwie der Lerneffekt ausgeblieben zu sein ^^ Btw.: Grundlagen sind immer hilfreich!