myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns
» Datenschutzerklärung
» Impressum

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » GUI: Windows-Forms » Eigene Button Klasse erstellen
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Eigene Button Klasse erstellen

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
ZeraTFK
myCSharp.de-Mitglied

Dabei seit: 11.03.2011
Beiträge: 4


ZeraTFK ist offline

Eigene Button Klasse erstellen

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top


mycsharp.de  Moderationshinweis von herbivore (12.03.2011 09:02):

Warnung an Leser, die ähnliches vorhaben: Der Code von ZeraTFK ist aus verschiedenen Gründen fehlerhaft und auch sonst nicht empfehlenswert. Bessere Lösungen finden ihr in den Links weiter unten.
 

Hi,

Ich habe da mal eine Frage.

Ich hatte vor ein Programm zu schreiben, welches aus einem einzigen Menü besteht.
Als erstes wollte ich eine eigene Klasse erstellen, welche eines Button gleicht.
Ich erzeuge auf der Hauptform das Objekt und dieses beinhaltet Folgende eigenschaften:

C#-Code:
public Image CImage { get; set; }
        public Image CImage_Hover { get; set; }
        public Image CImage_Push { get; set; }
        public Buttonstate Bstate { get; set; }
        public String CName { get; set; }
        public Point CPos { get; set; }
        public Size CSize { get; set; }
        Thread Event_Thread;

Nun brauche ich ja die Events die auch ein normaler Button hat.
Meine erste frage ist, sollte ich von Controls erben?

Ich dachte mir nein und habe eigene Events gemacht.
Da dies mein erstes mal ist, das ich Events mache, bin ich mir auch recht unsicher ob es stimmt was ich da gemacht habe.

Der Button hat nun diese Events:

C#-Code:
public event EventHandler<MouseEventArgs> On_MyMouseMove;
        public event EventHandler<MouseEventArgs> On_MyMouseLeave;
        public event EventHandler<MouseEventArgs> On_MyMouseDown;

Diese werden aber komischer weiße nur einmal im Programm ausgeführt und dann nie wieder, also dachte ich ich muss diese in ein Thread packen welcher im Konstruktor des Buttons gestartet wird.

Das wäre dann der Thread

C#-Code:
public void MyThread()
        {
            while (true)
            {
                //hier wird mit dem Server connected
                //dann musst du sagen, dass jetzt das Event ausgelöst werden soll
                if (this.On_MyMouseMove != null) //ist ein EventHandler zugewiesen?
                {
                    Point last_p = new Point(0, 0);

                    //GetCursorPos(ref MousePoint);
                    if (Cursor.Position.X >= CPos.X && Cursor.Position.X <= CPos.X + CSize.Width &&
                        Cursor.Position.Y >= CPos.Y && Cursor.Position.Y <= CPos.Y + CSize.Height)
                    {
                        if (last_p.X != Cursor.Position.X && last_p.Y != Cursor.Position.Y)
                        {
                            MouseEventArgs m = new MouseEventArgs(Button.MouseButtons, 0, Button.MousePosition.X, Button.MousePosition.Y, 0);

                            On_MyMouseMove(this, m);
                        }
                    }

                    last_p = new Point(Cursor.Position.X, Cursor.Position.Y);

                    Thread.Sleep(1);
                }


                if (this.On_MyMouseLeave != null) //ist ein EventHandler zugewiesen?
                {

                    //GetCursorPos(ref MousePoint);
                    if (Cursor.Position.X < CPos.X || Cursor.Position.X > CPos.X + CSize.Width ||
                        Cursor.Position.Y < CPos.Y || Cursor.Position.Y > CPos.Y + CSize.Height)
                    {
                        if (Bstate == Buttonstate.HOVER)
                        {
                            MouseEventArgs m = new MouseEventArgs(Button.MouseButtons, 0, Button.MousePosition.X, Button.MousePosition.Y, 0);

                            On_MyMouseLeave(this, m);
                            Bstate = Buttonstate.IDLE;
                        }
                    }
                }


                if (this.On_MyMouseDown != null) //ist ein EventHandler zugewiesen?
                {

                    //GetCursorPos(ref MousePoint);
                    if (Cursor.Position.X >= CPos.X && Cursor.Position.X <= CPos.X + CSize.Width &&
                        Cursor.Position.Y >= CPos.Y && Cursor.Position.Y <= CPos.Y + CSize.Height)
                    {
                        if (Bstate == Buttonstate.HOVER && Button.MouseButtons == MouseButtons.Left)
                        {
                            MouseEventArgs m = new MouseEventArgs(Button.MouseButtons, 0, Button.MousePosition.X, Button.MousePosition.Y, 0);

                            On_MyMouseDown(this, m);
                        }
                    }
                }
                Thread.Sleep(1);
            }
        }

In der Hauptform erzeuge ich den Button und teile die Evente zu

C#-Code:
CloseButton.On_MyMouseMove += new EventHandler<MouseEventArgs>(CloseButton_On_MyMouseMove);

            CloseButton.On_MyMouseLeave += new EventHandler<MouseEventArgs>(CloseButton_On_MyMouseLeave);

            CloseButton.On_MyMouseDown +=new EventHandler<MouseEventArgs>(CloseButton_On_MyMouseDown);

Das Move und Leave Event klappt perfekt... Die Grafiken ändern sich sobald das Event eintritt.



Nun mein eigentliches Problem:
Ich erzeuge einen CloseButton, welcher bei dem OnClick Event aus dem Thread des Buttons auf den Hauptthread springt und da folgende Funktion ausführt:

C#-Code:
public void CloseButton_On_MyMouseDown(object sender, MouseEventArgs e)
        {
            Close();
        }

Doch es kommt immer die Meldung:

Fehlermeldung:
Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement Form1 erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde.

Mache ich etwas an den Events falsch, da ich nicht glaube das Events in ein Thread müssen.. da wird mein Fehler sein oder?

Oder kann ich per delegaten die Hauptform Closen?
Habe das schon versucht doch ohne erfolg?!?



Danke im vorraus

Mit freundlichen Grüßen
Zera!
11.03.2011 16:20 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Aratar
myCSharp.de-Mitglied

Dabei seit: 28.10.2009
Beiträge: 118


Aratar ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

Ich habe den Code mal überflogen und hab das Gefühl, dass du etwas falsch verstanden hast.

Wieso nicht von Control erben?
Welchen Sinn sollen den Thread.Sleep und while(true) haben?

Ich würde das Ganze nochmal ordentlich überarbeiten, bzw. komplett neu schreiben.


Trotzdem, als Antwort auf dein Problem:
 [FAQ] Controls von Thread aktualisieren lassen (Control.Invoke/Dispatcher.Invoke)

Mfg
Aratar
11.03.2011 16:56 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
ZeraTFK
myCSharp.de-Mitglied

Dabei seit: 11.03.2011
Beiträge: 4

Themenstarter Thema begonnen von ZeraTFK

ZeraTFK ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ich habe es schon versucht von Control zu erben, doch wenn ich dann alles eingestellt habe, ist meine eigene Grafik die ich aus der Klasse erhaus male weg und stattdessen ist da ein Graues viereck wo eigntlich die Grafik des Buttons ist.

Und das Sleep habe ich eingebaut, da ich so CPU Leistung erhalten möchte.

Danke für deine schnelle Antwort! Ich werde es mal damit versuchen.
11.03.2011 17:15 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.271
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo ZeraTFK,

ich kann mich Aratar nur anschließen: dein Code ist kompletter Unsinn.

Aber trotzdem noch mal die Nachfrage: es geht um WinForms, oder?
Dann darfst du den UI-Thread nicht blockieren, s.a.  [FAQ] Warum blockiert mein GUI? und auch keine Controls außerhalb des UI-Threads erzeugen.

Um einen eigenen Button (in WinForms) zu erzeugen, gibt es viele andere Möglichkeiten, s. z.B.
 http://www.codeproject.com/KB/buttons/xp-style_button.aspx
 http://www.codeproject.com/KB/buttons/XCtrls.aspx
 http://www.codeproject.com/KB/buttons/Ro...ton_csharp.aspx
 http://www.codeproject.com/KB/buttons/RoundButton.aspx

Edit: ein Beispiel für einen dynamischeren Button (mit Animation) gibt es unter
 http://www.codeproject.com/KB/buttons/PulseButton.aspx

Du brauchst also weder eigene Threads noch die Standardevents nachzubauen...

Hauptansatz ist einfach das Überschreiben der Paint-Methode, s.a.  [Tutorial] Zeichnen in Windows-Programmen (Paint/OnPaint, PictureBox)

Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Th69 am 11.03.2011 18:06.

11.03.2011 17:51 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
ZeraTFK
myCSharp.de-Mitglied

Dabei seit: 11.03.2011
Beiträge: 4

Themenstarter Thema begonnen von ZeraTFK

ZeraTFK ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Ich habe es nun allein hinbekommen, dank des Links von Aratar.
Musste den Code auch gar nicht großartig umändern und musste dennoch nicht Erben.
Es Funktioniert besser als ich dachte also kann der Code auch gar nicht so Unsinnig sein ;)
11.03.2011 18:56 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Th69
myCSharp.de-Poweruser/ Experte

avatar-2578.jpg


Dabei seit: 01.04.2008
Beiträge: 3.271
Entwicklungsumgebung: Visual Studio 2015/17


Th69 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Doch, deine gesamte Thread-Methode ist überflüssig und daher unsinnig!
Außerdem laufen die ausgelösten Events dann auch im Nebenthread, d.h. in der Event-Methode müßte man zum Zugriff auf die UI dann auch wieder 'invoken'.
Und 1000 mal pro Sekunde die Mausposition per Polling abzufragen, ist auch mehr als schlechter Programmierstil.
Und ich tippe darauf, daß du für jeden Button wahrscheinlich diese Thread-Methode aktiv aufrufst (d.h. je mehr Buttons, um so mehr Threads -> Performance-Killer).

Ich weiß nicht, woher du diesen Programmierstil hast, aber dieser Beitrag hat wirklich Potential auf den Titel "DAU des Monats" bzw.  Coding Styles Horror ;-)

Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von Th69 am 11.03.2011 19:36.

11.03.2011 19:34 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 8 Jahre.
Der letzte Beitrag ist älter als 8 Jahre.
Antwort erstellen


© Copyright 2003-2019 myCSharp.de-Team | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 16.07.2019 20:49