eigene windows Forms Steuerelemente bauen



  • Hallo,
    Ich möchte gerne eigene Steuerelemente machen. Ich habe das folgendermaßen realisiert:

    #pragma once
    
    namespace neuControl {
    
    	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::Drawing::Drawing2D;
    
    	public ref class Zeitanzeige : Control {
    		protected: void OnPaint(PaintEventArgs e) {
    			Rectangle r(0, 0, this->Width, this->Height); 
    			LinearGradientBrush^ b = gcnew LinearGradientBrush(r, Color::Blue, Color::White,System::Drawing::Drawing2D::LinearGradientMode::BackwardDiagonal); 
    			e.Graphics->FillRectangle(b, r); 
    			String^ time = gcnew String(DateTime::Now.ToShortTimeString()); 
    			System::Drawing::Font^ f = gcnew System::Drawing::Font(L"Palatino Linotype", 8.25F, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point, static_cast<System::Byte>(0));
    			SizeF s = e.Graphics->MeasureString(time, f); 
    			e.Graphics->DrawString(time, f, Brushes::YellowGreen, 
    			PointF(this->Width / 2 - s.Width / 2, 
    			this->Height / 2 - s.Height / 2)); 
    		}
    	};
    
    	/// <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;
    			}
    		}
    	private: Zeitanzeige^ za;
    	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->za = (gcnew Zeitanzeige());
    			this->SuspendLayout();
    			// 
    			// Form1
    			// 
    			this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
    			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
    			this->ClientSize = System::Drawing::Size(468, 374);
    			this->Controls->Add(this->za);
    			this->Name = L"Form1";
    			this->Text = L"Form1";
    			this->ResumeLayout(false);
    
    		}
    #pragma endregion
    	};
    }
    

    Keine Übersetzungsfehler, aber er zeigt schlicht weg níchts an, außer dem leeren Form.

    Woran liegts?



  • Du lädst ja auch kein Steuerelement.
    Aber warum machst Du das so und nich so?...

    http://www.rb-softarticle.com/Box.rar

    Ist besser, aber auch nur ein Vorschlag.

    Gruß, Doug_HH



  • Du meinst vom Prinzip her, das man mehrere schon vorhandene Elemente nimmt und sie zu einem neuen "verbindet". Das Problem ist nur, ich wollte so einen versctellbaren Balken bauen, der dann z.b. eine Skala hat, an der man etwas einstellen kann. Das lässt sich nur schwer aus dem vorhandenen zusammenbasteln.

    Du lädst ja auch kein Steuerelement.

    Was genau meinst Du damit?



  • Ich meine damit, was in meinem Beispiel über den Button gemacht wird.

    Du vereinbarst zwar...

    protected: void OnPaint(PaintEventArgs e)
    

    ...aber greifst nie drauf zu.

    Debug doch mal Dein Code. Der Code wird nicht ausgeführt, das meine ich damit.

    Bevor wir jetzt ganz aneinander vorbeireden.

    Du legst eine ganz normale "Windows Forms Anwendung" an, und möchtest diese Windows Forms dann in andere Programme als OCX benutzen?
    Oder möchtest Du ein Steuerelement für Deine erstellte Windows Forms Anwendung verwenden?

    Du kannst in den Beispiel auch die Linien und Kurven und wie auch immer dynamisch erstellen, das ist nicht das Problem.

    Gruß, Doug_HH



  • ...aber greifst nie drauf zu.

    Ich verstehe...

    Du legst eine ganz normale "Windows Forms Anwendung" an, und möchtest diese Windows Forms dann in andere Programme als OCX benutzen?
    Oder möchtest Du ein Steuerelement für Deine erstellte Windows Forms Anwendung verwenden?

    Du kannst in den Beispiel auch die Linien und Kurven und wie auch immer dynamisch erstellen, das ist nicht das Problem.

    Ich möchte ein einfaches Steuerelement erstellen, das am besten sogar später auch in der Toolbox auftaucht(falls das möglich ist), das ich dann in meinen Anwendungen benutzen kann.



  • Lass dich von solchen Aussagen nicht verwirren Mr X, denn sie stimmt net

    Doug_HH schrieb:

    Du vereinbarst zwar...

    protected: void OnPaint(PaintEventArgs e)
    

    ...aber greifst nie drauf zu.

    OnPaint ist ja nicht irgendeine Methode sondern wird automatisch aufgerufen wenn ein Zeichnen erforderlich ist, die darf man gar nicht manuell aufrufen.

    Du gibst nur nirgends die Größe deines Controls an. Dann wirds wahrscheinlich nur als 0x0 großes Ding angezeigt. Änder mal das und dann am besten auch gleich noch ne ordentliche Position und dann müssts eigentlich gehen. Prizipiell siehts nämlich gut aus.

    EDIT: Vergiss net den Brush und Font zu disposen, sonst läuft deine App net lang weil die Resourcen ausgehen.



  • Talla schrieb:

    Lass dich von solchen Aussagen nicht verwirren Mr X, denn sie stimmt net

    Autsch, das tut weh "Talla", Du verwechselst die OnPaint wohl mit der Paint...

    private: System::Void Form1_Paint(System::Object^  sender, System::Windows::Forms::PaintEventArgs^  e) 
    			 {
    			 }
    

    Also solltest Du den Code auch mal Debugen...

    http://www.rb-softarticle.com/Debug.html

    Oder pack noch mal ein Pfund Größe drauf 🙄
    Wird schon klappen...
    Aber sonst, Guter Vorschlag...

    /Edit/

    Ach so, das wird so nicht in der Toolbox auftauchen, da Du eine EXE Anwendung erstellst.
    Du müsstest dann schon eine „Windows Forms-Steuerelementbibliothek“ (OCX) anlegen.

    http://www.rb-softarticle.com/Pic.jpg

    Ich hoffe, dass ich diesmal richtig liege. 😕

    Gruß, Doug_HH



  • Und du hast anscheinend Wissenslücken wie Windows Forms funktionieren und wie Events implementiert werden. OnPaint ist die Funktion die das entsprechende Paint Event erst auslöst das du nennst - ich verwechsle da gar nichts! Wenn man die überschreibt packt man dort seinen Zeichencode rein und sobald Windows denkt das Control müsse sich neuzeichnen dann wird die Funktion aufgerufen.

    Wie gesagt, gib dem Control ne Größe (das ist wichtig, da nur da sgezeichnet wird was auch sichtbar ist), pass die Signatur der Funktion an (hab grad erst gesehen das die auch noch net ganz stimmt) und dann tuts. Hoffe dann ist die Überheblichkeit auch nimmer ganz so groß...

    Aus

    void OnPaint(PaintEventArgs e)
    

    muss du

    virtual void  OnPaint(PaintEventArgs ^e) override
    

    machen und auch entsprechend den Code bissle ändern da ^e ja jetzt nen Handle ist. Durch die falsche Signatur hat er die Funktion nicht wie gewünscht überschrieben und deshalb hat er nichts gezeichnet.



  • Talla schrieb:

    Und du hast anscheinend Wissenslücken wie Windows Forms funktionieren und wie Events implementiert werden. OnPaint ist die Funktion die das entsprechende Paint Event erst auslöst das du nennst - ich verwechsle da gar nichts! Wenn man die überschreibt packt man dort seinen Zeichencode rein und sobald Windows denkt das Control müsse sich neuzeichnen dann wird die Funktion aufgerufen.

    Es kann schon sein das ich nicht alles von Windows Forms weiß, aber der Debuger ist für mich schon ein wichtiges Werkzeug.
    Und zum anderen sehe ich auch, dass OnPaint der Form nicht bekannt ist.



  • Hast du meine Änderungen ausprobiert? Tu es bitte, dann siehst du das die Funktion sehr wohl aufgerufen wird. Und wenn du mir nicht glaubst das OnPaint eine Funktion der Form ist, dann schau in die Doku, dort stehts schwarz auf weiß.



  • So das funktioniert jetzt. Danke!



  • Kannst Du bitte mal den Code posten...
    Weil das haut so nicht hin?

    #pragma once
    
    namespace teses {
    
    	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::Drawing::Drawing2D;
    
    	 public ref class Zeitanzeige : Control 
    	 { 
            virtual void  OnPaint(PaintEventArgs ^e) override
    		{ 
                Rectangle r(0, 0, this->Width, this->Height); 
                LinearGradientBrush^ b = gcnew LinearGradientBrush(r, Color::Blue, Color::White,System::Drawing::Drawing2D::LinearGradientMode::BackwardDiagonal); 
                e.Graphics->FillRectangle(b, r); 
                String^ time = gcnew String(DateTime::Now.ToShortTimeString()); 
                System::Drawing::Font^ f = gcnew System::Drawing::Font(L"Palatino Linotype", 8.25F, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point, static_cast<System::Byte>(0)); 
                SizeF s = e.Graphics->MeasureString(time, f); 
                e.Graphics->DrawString(time, f, Brushes::YellowGreen, 
                PointF(this->Width / 2 - s.Width / 2, 
                this->Height / 2 - s.Height / 2)); 
            } 
        }; 
    
    	/// <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;
    			}
    		}
    
    	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->components = gcnew System::ComponentModel::Container();
    			this->Size = System::Drawing::Size(300,300);
    			this->Text = L"Form1";
    			this->Padding = System::Windows::Forms::Padding(0);
    			this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
    		}
    #pragma endregion
    	};
    }
    

    Gruß, Doug_HH



  • public ref class Zeitanzeige : Control {
    		protected: virtual void  OnPaint(PaintEventArgs ^e) override {
    			Rectangle r(0, 0, this->Width, this->Height); 
    			LinearGradientBrush^ b = gcnew LinearGradientBrush(r, Color::Blue, Color::White,System::Drawing::Drawing2D::LinearGradientMode::BackwardDiagonal); 
    			e->Graphics->FillRectangle(b, r); 
    			String^ time = gcnew String(DateTime::Now.ToShortTimeString()); 
    			System::Drawing::Font^ f = gcnew System::Drawing::Font(L"Palatino Linotype", 8.25F, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point, static_cast<System::Byte>(0));
    			SizeF s = e->Graphics->MeasureString(time, f); 
    			e->Graphics->DrawString(time, f, Brushes::YellowGreen, PointF(this->Width / 2 - s.Width / 2, this->Height / 2 - s.Height / 2)); 
    		}
    	};
    

    Das ist der Code für das Steuerelement.
    Zum benutzen ganz einfach ganz normal ein Objekt des Typs erstellen(Ich habs mir einfach vom Designer abgeschaut weil ich Drag&Drop gewöhnt bin 🤡 )



  • Für welches Framework soll dies übersetzt werden ?



  • Das war doch genau was ich gemeint habe...

    this->zeitAnz = (gcnew Zeitanzeige());
    this->zeitAnz->Location = System::Drawing::Point(10,95);
    this->zeitAnz->Size = System::Drawing::Size(75,23);
    this->Controls->Add(this->zeitAnz);
    

    Wenn Du jetzt den Haltepunkt in OnPaint setzt, wird die Funktion auch ausgeführt...

    private: Zeitanzeige^ zeitAnz;
    

    Zuvor wußte die Form nix von Zeitanzeige...

    Hab ich mich falsch ausgedrückt?

    So einfach war die Änderung ja nun doch nicht?

    Aber sieht nett aus die Anzeige.

    Gruß, Doug_HH



  • du meintest das Delegates durch ein Wunder ausgelöst werden 😃



  • majin schrieb:

    du meintest das Delegates durch ein Wunder ausgelöst werden 😃

    Ja genau, dass meinte der Autor wohl 😃



  • Ich hole diesen Thread nochmal nach vorne, denn meine Frage bezieht sich darauf...:

    Dough_HH hatte ja ein Beispiel online gestellt(leider nicht mehr online), indem eine Komponentenklasse genutzt wurde. Ich habe nun versucht, so etwas auch zu nutzen(in diesem Fall ist es wohl sinnvoller als selbstgemalt), aber leider kann ich nicht so schön per Drag&Drop arbeiten, wie dies bei dem Beispiel der Fall war.

    Ich habe eine Komponentenklasse genommen, und aus der Toolbox ein Label darauf gesetzt, jedoch wird es nicht so angezeigt, wie bei einem Form.
    Woran liegt das, das ich das nicht so hinbekommen habe?



  • Was meinst du damit dass es nicht so angezeigt wird wie bei einer Form?



  • Das man den Designer so benutzen kann, wie bei einem normalen Form.

    Sorry für meine unverständliche und umständliche Erklärung 🙄


Anmelden zum Antworten