Objekt übergabe geht nicht?
-
Also ich habe ein Hauptprogramm mit einer Textbox darin.
Es wird beim laden ein thread erzeugt und und über diesen auf das GUI zugegriffen (funktioniert auch mittels Invoke).
Jetzt will ich diesen Zugriff auf das GUI aber in eine andere *.cpp datei auslagern. In der anderen *.cpp datei bekomm ich dann aber keinen zugriff mehr auf das Textbox objekt?? (wollte es schon als Parameter übergeben aber irgendwie Funktionierte dies nicht )
Wie würde das in meinen bsp. aussehen oder wie könnte ich das sonst lösen?Hier mein Code:
// DemoModul2008.cpp : main project file. #include "stdafx.h" #include "Form1.h" #include <stdio.h> using namespace System; using namespace DemoModul2008; [STAThreadAttribute] int main(array<System::String ^> ^args) { // Enabling Windows XP visual effects before any controls are created Application::EnableVisualStyles(); Application::SetCompatibleTextRenderingDefault(false); // Create the main window and run it Application::Run(gcnew Form1()); //Application::Run(test); return 0; }
Form1.h :
#pragma once #include "FW.h" #using <mscorlib.dll> namespace DemoModul2008 { using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; using namespace System::Threading; /// <summary> /// Summary for Form1 /// /// WARNING: If you change the name of this class, you will need to change the /// 'Resource File Name' property for the managed resource compiler tool /// associated with all .resx files this class depends on. Otherwise, /// the designers will not be able to interact properly with localized /// resources associated with this form. /// </summary> public ref class Form1 : public System::Windows::Forms::Form { private: Thread ^trd; delegate void DelegateThreadTask(); public: delegate void AddListItem( String^ myString ); AddListItem^ myDelegate; public: void SchreibeInTextBox() //void SchreibeInTextBox(char*) { if (textBox1->InvokeRequired == false) textBox1->AppendText("TEST"); else { DelegateThreadTask ^myThreadDelegate = gcnew DelegateThreadTask(this,&DemoModul2008::Form1::SchreibeInTextBox); this->Invoke(myThreadDelegate); } } public: Form1(void) { InitializeComponent(); // //TODO: Add the constructor code here // } protected: /// <summary> /// Clean up any resources being used. /// </summary> ~Form1() { if (components) { delete components; } // if (trd->IsAlive) trd->Abort();//Tread stoppen } public: System::Windows::Forms::TextBox^ textBox1; protected: private: System::Windows::Forms::Label^ label1; private: System::Windows::Forms::Button^ button1; private: /// <summary> /// Required designer variable. /// </summary> System::ComponentModel::Container ^components; #pragma region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> void InitializeComponent(void) { this->textBox1 = (gcnew System::Windows::Forms::TextBox()); this->label1 = (gcnew System::Windows::Forms::Label()); this->button1 = (gcnew System::Windows::Forms::Button()); this->SuspendLayout(); // // textBox1 // this->textBox1->Location = System::Drawing::Point(12, 66); this->textBox1->Multiline = true; this->textBox1->Name = L"textBox1"; this->textBox1->Size = System::Drawing::Size(591, 311); this->textBox1->TabIndex = 0; // // label1 // this->label1->AutoSize = true; this->label1->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 22, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, static_cast<System::Byte>(0))); this->label1->Location = System::Drawing::Point(100, 14); this->label1->Name = L"label1"; this->label1->Size = System::Drawing::Size(397, 36); this->label1->TabIndex = 1; this->label1->Text = L"multiWin DemoModul 2008"; // // button1 // this->button1->Location = System::Drawing::Point(637, 104); this->button1->Name = L"button1"; this->button1->Size = System::Drawing::Size(57, 44); this->button1->TabIndex = 2; 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(750, 389); this->Controls->Add(this->button1); this->Controls->Add(this->label1); this->Controls->Add(this->textBox1); this->Name = L"Form1"; this->Text = L"Form1"; this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load); this->ResumeLayout(false); this->PerformLayout(); } #pragma endregion private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { this->textBox1->AppendText("TEST"); } private: void repeat() { this->SchreibeInTextBox(); //Funktioniert Fehlerfrei mainFW(); //hierin Funktioniert SchreibeInTextBox nicht mehr !!! } private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) { ThreadStart ^myThreadDelegate = gcnew ThreadStart(this, &DemoModul2008::Form1::repeat); trd = gcnew Thread(myThreadDelegate); trd->IsBackground = true; trd->Start();//eventuell noch mit join } }; }
FW.h :
//Andre` header für Haulo main //#ifndef __FW_H //#define __FW_H #include "Form1.h" void mainFW(); void VorInitialisierung(void); //#endif
FW.cpp :
#include "stdafx.h" #include "Form1.h" void mainFW()//darf nicht main heissen - Andre` { DemoModul2008::Form1::SchreibeInTextBox(); //FEHLER illegal call of non static Member function }
-
Hallo,
Du könntest dem Thread die Form1 Instanz als Parameter übergeben.
Dazu musst Du allerdings nicht den ThreadStart, sondern den ParameterizedThreadStart Delegaten verwenden.Hier die Doku mit Bsp.:
http://msdn2.microsoft.com/en-us/library/1h2f2459.aspxSimon
-
Verstehst Du C# ein wenig?
-
simon.gysi schrieb:
Hallo,
Du könntest dem Thread die Form1 Instanz als Parameter übergeben.
Dazu musst Du allerdings nicht den ThreadStart, sondern den ParameterizedThreadStart Delegaten verwenden.Hier die Doku mit Bsp.:
http://msdn2.microsoft.com/en-us/library/1h2f2459.aspxSimon
versteh schon ein wenig c#.
Im Thread ist doch aber die Form 1 instanz vorhanden - im thread läuft doch repeat() und darin kann ich ja mit this->SchreibeInTextBox auf die textbox zugreifen. Ich bekomm blos dann in der ausgelagerten mainFW() keinen zugriff mehr. Hab jetzt schon Probiert mainFW(this) und den this Zeiger zu übergeben aber da hat er mir immer im header dazu eine Fehlermeldung gebracht - hoffe konnte mir noch wer folgen...
-
m Thread ist doch aber die Form 1 instanz vorhanden - im thread läuft doch repeat() und darin kann ich ja mit this->SchreibeInTextBox auf die textbox zugreifen.
Im Thread (= in der Thread Funktion, also ?::repeat()) hast Du aber nur dann eine Instanz von Form1, weil Du mit this darauf zugreifst und Du eben repeat in Form1 implmenteirt hast.
Ich versuche Dir ein C# Bsp. zu machen, da ich momentan keinen C++/CLI Kompiler zur Verfügung habe.
-
simon.gysi schrieb:
m Thread ist doch aber die Form 1 instanz vorhanden - im thread läuft doch repeat() und darin kann ich ja mit this->SchreibeInTextBox auf die textbox zugreifen.
Im Thread (= in der Thread Funktion, also ?::repeat()) hast Du aber nur dann eine Instanz von Form1, weil Du mit this darauf zugreifst und Du eben repeat in Form1 implmenteirt hast.
Ich versuche Dir ein C# Bsp. zu machen, da ich momentan keinen C++/CLI Kompiler zur Verfügung habe.
hmm ja da hast du wohl recht. Aber wie mach ich dann so einen thread auf das ich das Form1 Objekt in den Thread übergeben kann? - bzw.wie komm ich überhaupt an das Objekt ran ausser mit this?
-
Hier ist das C# Bsp. Dies hier ist nur eine Möglichkeit... es gibt viele andrere.
Simon
using System; using System.Threading; using System.Windows.Forms; namespace ThreadTest { public partial class Form1 : Form { private Thread thread = null; private Worker worker = new Worker(); public Form1() { InitializeComponent(); } private void Form1Load(object sender, EventArgs e) { thread = new Thread(new ParameterizedThreadStart(worker.DoWork)); thread.IsBackground = true; thread.Start(this); } private void Form1FormClosing(object sender, FormClosingEventArgs e) { thread.Abort(); thread.Join(); } private delegate void WriteToTextBoxDelegate(String str, bool append); public void WriteToTextBox(String str, bool append) { if (InvokeRequired) { Invoke(new WriteToTextBoxDelegate(WriteToTextBox), new object[] { str, append }); } else { if (append) outputTextBox.Text += str; else outputTextBox.Text = str; } } } internal class Worker { public void DoWork(object obj) { try { Form1 form1 = obj as Form1; if (form1 == null) { throw new ArgumentException(); } for (int i = 0; i < 75; ++i) { form1.WriteToTextBox(".", true); Thread.Sleep(100); } form1.WriteToTextBox(String.Empty, false); } catch(ThreadAbortException) {} } } }
-
Super - vielen dank schonmal.
Hab das jetzt soweit gemacht - habe aber das Problem das ich in der ThreadFunktion auf dem objekt wo ich ja this für reingebe nicht an die SchreibeInTextBox() funktion rankommestatic void repeat(Object^ data)
{
data->SchreibeInTextBox();//geht nicht - wie sonst??
}nochmal der Komplette Code:
#pragma once #using <mscorlib.dll> #include "FWtest.h" namespace DemoModul2008 { using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; using namespace System::Threading; /// <summary> /// Summary for Form1 /// /// WARNING: If you change the name of this class, you will need to change the /// 'Resource File Name' property for the managed resource compiler tool /// associated with all .resx files this class depends on. Otherwise, /// the designers will not be able to interact properly with localized /// resources associated with this form. /// </summary> public ref class Form1 : public System::Windows::Forms::Form { //#include "FW.h" // private: Thread ^trd; // private: Thread^ newThread; delegate void DelegateThreadTask(); public: void SchreibeInTextBox() //void SchreibeInTextBox(char*) { if (textBox1->InvokeRequired == false) textBox1->AppendText("TEST"); else { DelegateThreadTask ^myThreadDelegate = gcnew DelegateThreadTask(this,&DemoModul2008::Form1::SchreibeInTextBox); this->Invoke(myThreadDelegate); } } public: Form1(void) { InitializeComponent(); // //TODO: Add the constructor code here // } protected: /// <summary> /// Clean up any resources being used. /// </summary> ~Form1() { if (components) { delete components; } // if (trd->IsAlive) trd->Abort();//Tread stoppen } public: System::Windows::Forms::TextBox^ textBox1; protected: private: System::Windows::Forms::Label^ label1; private: System::Windows::Forms::Button^ button1; private: /// <summary> /// Required designer variable. /// </summary> System::ComponentModel::Container ^components; #pragma region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> void InitializeComponent(void) { this->textBox1 = (gcnew System::Windows::Forms::TextBox()); this->label1 = (gcnew System::Windows::Forms::Label()); this->button1 = (gcnew System::Windows::Forms::Button()); this->SuspendLayout(); // // textBox1 // this->textBox1->Location = System::Drawing::Point(12, 66); this->textBox1->Multiline = true; this->textBox1->Name = L"textBox1"; this->textBox1->Size = System::Drawing::Size(591, 311); this->textBox1->TabIndex = 0; // // label1 // this->label1->AutoSize = true; this->label1->Font = (gcnew System::Drawing::Font(L"Microsoft Sans Serif", 22, System::Drawing::FontStyle::Bold, System::Drawing::GraphicsUnit::Point, static_cast<System::Byte>(0))); this->label1->Location = System::Drawing::Point(100, 14); this->label1->Name = L"label1"; this->label1->Size = System::Drawing::Size(397, 36); this->label1->TabIndex = 1; this->label1->Text = L"multiWin DemoModul 2008"; // // button1 // this->button1->Location = System::Drawing::Point(637, 104); this->button1->Name = L"button1"; this->button1->Size = System::Drawing::Size(57, 44); this->button1->TabIndex = 2; 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(750, 389); this->Controls->Add(this->button1); this->Controls->Add(this->label1); this->Controls->Add(this->textBox1); this->Name = L"Form1"; this->Text = L"Form1"; this->Load += gcnew System::EventHandler(this, &Form1::Form1_Load); this->ResumeLayout(false); this->PerformLayout(); } #pragma endregion private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) { this->textBox1->AppendText("TEST"); } private: System::Void Form1_Load(System::Object^ sender, System::EventArgs^ e) { Thread^ newThread = gcnew Thread(gcnew ParameterizedThreadStart(&DemoModul2008::Form1::repeat)); newThread->IsBackground = true; newThread->Start(this); /* //OLD VERSION ThreadStart ^myThreadDelegate = gcnew ThreadStart(this, &repeat); trd = gcnew Thread(myThreadDelegate); trd->IsBackground = true; trd->Start();//eventuell noch mit join */ } static void repeat(Object^ data) { data->SchreibeInTextBox(); //Form1 form1 = data as Form1; /* this->SchreibeInTextBox(); //Funktioniert Fehlerfrei //mainFW(this); //hierin Funktioniert SchreibeInTextBox nicht mehr !!! mainFW2(this); //hierin Funktioniert SchreibeInTextBox nicht mehr !!! */ } }; }
-
Du musst deine Object^ noch in eine Form^ Referenz casten.
Ungefähr so:static void repeat(Object^ data) { Form1^ form = safe_cast<Form1^>(data); form->SchreibeInTextBox(); }
-
simon.gysi schrieb:
Du musst deine Object^ noch in eine Form^ Referenz casten.
Ungefähr so:static void repeat(Object^ data) { Form1^ form = safe_cast<Form1^>(data); form->SchreibeInTextBox(); }
oh SUPER - DANKE DANKE DANKE!!!!!!