Progressbar mit Prozentanzeige flimmert



  • Hallo,

    ich nutze in meiner Applikation eine Continious Progressbar mit einer Prozentanzeige. Während die Progressbar läuft, flimmert sie ständig. Dieses Verhalten ist aber weg, wenn ich das Zeichnen der Prozentanzeige weglasse.
    Vielleicht erkennt jemand von euch, woran das liegen könnte. Hier meine Methode die ich für jeden Step der Progressbar nutze:
    (Der Backgroundworker mit dem ReportProgress kommt nicht in Frage!)

    private void UpdateProgressBarSteps(Object[] Args)
            {
                string Text = Args[1].ToString();
                Application.DoEvents();
                this.PRB_Progress.PerformStep();
                Font TextFont = new Font("Arial", 9, FontStyle.Bold);
                if (string.IsNullOrEmpty(Text))
                {
                    Application.DoEvents();
                    int percent = (int)(((double)(this.PRB_Progress.Value - this.PRB_Progress.Minimum) /
                        (double)(this.PRB_Progress.Maximum - this.PRB_Progress.Minimum)) * 100);
                    Text = percent.ToString() + "%";
                }
    
                using (Graphics gr = this.PRB_Progress.ProgressBar.CreateGraphics())
                {
                    gr.DrawString(Text,
                    TextFont,
                    new SolidBrush((Color)Args[2]),
                    new PointF(
                        this.PRB_Progress.Width / 2 - (gr.MeasureString(Text, //Centered
                        TextFont).Width / 2.0F),
                    this.PRB_Progress.Height / 2 - (gr.MeasureString(Text,
                        TextFont).Height / 2.0F)));
                }
            }
    


  • Application.DoEvents(..) ist böse und soll nicht genutzt werden!
    Lies dir dazu den folgenden Thread durch:
    http://www.c-plusplus.net/forum/208458

    Dein geflicker kann damit zu tun haben!

    [EDIT]

    (Der Backgroundworker mit dem ReportProgress kommt nicht in Frage!)

    Warum nicht?



  • Vielleicht reicht es, daß Du nur flackerst, wenn der Text sich tatsächlich ändert.



  • Application.DoEvents(..) ist böse und soll nicht genutzt werden!

    Ehrlich gesagt hat das Application.DoEvents() das Flimmern etwas reduziert.

    (Der Backgroundworker mit dem ReportProgress kommt nicht in Frage!)
    Warum nicht?

    Kurz und knapp: So ist meine Vorgabe (hatte auch schon gefragt, wäre damit ja einfacher).

    Vielleicht reicht es, daß Du nur flackerst, wenn der Text sich tatsächlich ändert.

    Du meinst, dass ich den Text nur neu zeichne, wenn sich was geändert hat?

    Mit flimmern/flackern meine ich, dass während die ProgressBar läuft, sie der Füllbalken manchmal (sporadisch) kurzzeitig flimmert/flackert, wie ein schlechtes Bild am Fernseher.



  • Hi,

    setzt doch mal ein

    SetStyle( ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);
    

    in den Ctor deiner Progressbar



  • Hallo Barbar,

    was meinst du mit:

    in den Ctor deiner Progressbar

    Wo soll ich das reinmachen?



  • Ctor = Konstruktor



  • Keine Veränderung. Das Flimmern besteht weiterhin.



  • Das Flimmern wirst du auf deine Art (Application.DoEvents, CreateGraphics) auch nicht wegbekommen, da dein Source-Code entgegen jeder üblichen Konvention programmiert ist.
    Nimm lieber eines der Progressbar-Controls von CodeProject, s. mein Beitrag im C-Sharp-Forum: http://www.c-sharp-forum.de/viewtopic.php?p=623553#623553


  • Administrator

    Ich habe eine einfache Vermutung:
    Du zeichnest ja nicht in OnPaint der ProgressBar sondern ausserhalb. Du löst aber durch das PerformStep eine WM_PAINT aus. Was also wirklich passiert, ist das folgende:
    1. Deine UpdateProgressBarSteps wird aufgerufen.
    2. Du rufst PerformStep auf, die Nachricht WM_PAINT wird in die Nachrichtenschleife gesetzt, aber noch nicht ausgeführt!
    3. Du zeichnest auf die ProgressBar .
    4. UpdateProgressBarSteps wird beendet / gibt zurück.
    5. Nun wird die WM_PAINT Nachricht behandelt.
    6. Der Hintergrund wird gezeichnet, darüber das Control , usw. Schlussendlich verschwindet dabei dein Text!
    7. Es wird womöglich bereits wieder UpdateProgressBarSteps aufgerufen, wodurch nach kurzem Flackern dein Text wieder erscheint.
    8. usw.

    Daher: NIE ausserhalb der WM_PAINT Nachricht zeichnen! Registrier dich beim Paint Event der ProgressBar und zeichne deinen Text dort!

    Edit: Eine fertige Lösung zu nehmen, wie dies Th69 vorschlägt, ist natürlich ebenfalls eine sinnvolle Alternative 🙂

    Grüssli



  • @Dravere:
    Du lagst gold richtig.

    @Th69
    [cs]Source-Code entgegen jeder üblichen Konvention programmiert ist[/cs]
    Unpräzise Ausdrucksweise: "üblich" --> Eher gegen deine Möchtegern-Konvention. Idealist (bitte nachschlagen).



  • @Th69

    Source-Code entgegen jeder üblichen Konvention programmiert ist
    

    Unpräzise Ausdrucksweise: "üblich" --> Eher gegen deine Möchtegern-Konvention. Idealist (bitte nachschlagen).

    Nicht nur seine...


  • Administrator

    Husic8342345 schrieb:

    Th69 schrieb:

    Source-Code entgegen jeder üblichen Konvention programmiert ist

    Unpräzise Ausdrucksweise: "üblich" --> Eher gegen deine Möchtegern-Konvention. Idealist (bitte nachschlagen).

    Die Konvention ist grundsätzlich von Microsoft und stellt eine sinnvolle Vorgehensweise dar, damit man nicht auf Probleme stösst. Zum Beispiel gehört dazu, dass man nicht ausserhalb der WM_PAINT zeichnet. Auch sollte man auf Application.DoEvents verzichten. Microsoft schreibt dazu in der Dokumentation selber, dass man sowas nur aufrufen sollte, wenn man längere Aufgaben abarbeitet und sogar dann, extra mit einer gelben Vorsichtbox hervorgehoben, sollte man besser asynchrone Konzepte bevorzugen. Auch findet man dazu zahlreiche Einträge in den MSDN Blogs oder von anderen namhaften .Net Entwickler.

    Zudem sollte man sowas dann sowieso gleich in eine eigene Klasse verfrachten, welche von ProgressBar erbt, damit die Funktionalitäten getrennt sind. Das wiederrum ist ein Prinzip aus der objektorientierten Programmierung. Wird aber ebenfalls von Microsoft auf den MSDN Seiten so beworben. Hier ein Link zu Themen über das Entwicklen von eigenen Controls für WinForms:
    http://msdn.microsoft.com/en-us/library/6hws6h2t.aspx

    Das einzige, was man an der Aussage von Th69 kritisieren kann, ist, dass er die Aussage einfach nur so in den Raum gestellt hat, ohne zu sagen, wie denn die tatsächliche Konvention ist. Der Link oben zur MSDN Seite hätte schon genügt 🙂

    Grüssli



  • @theta:
    ACK

    @Husic8342345:
    Wieso reagieren Anfänger (damit meine ich dich) immer (oft) so empfindlich, wenn man ihnen sagt, dass sie was falsch machen?


  • Administrator

    hustbaer schrieb:

    @Husic8342345:
    Wieso reagieren Anfänger (damit meine ich dich) immer (oft) so empfindlich, wenn man ihnen sagt, dass sie was falsch machen?

    Weil sie sich angegriffen fühlen, vor allem bei so pauschalen Aussagen wie sie Th69 gemacht hat. Das klingt für einen Anfänger so: "Du hast alles falsch gemacht! Das ist absoluter Scheiss!"
    Daher bin ich der Meinung, dass man dies anders formulieren sollte: Weniger aggressiv und gleich mit einer Lösung. Man sollte sagen: "Hey! Das ist nicht so gut, schau wie es Experten machen und empfehlen. Damit hast du viel weniger Probleme!"

    Wenn einfach jemand daher kommt und sagt "Das ist Konvention!", ohne dazu jeglichen Beweis zu präsentieren, bringt das niemandem etwas und glauben tut man es ihm auch nicht wirklich. Das ist sogar später noch der Fall, wenn man nicht mehr Anfänger ist 😉

    Natürlich gibt es dann auch immer noch Sturrköpfe bei den Anfängern (auch bei den "Experten"), welche ihre Fehler partout nicht einsehen wollen. Entweder lernen sie es dann verzögert einmal oder gar nie. Das hängt dann aber eher am Charackter der Person und weniger damit, dass die Person Anfänger ist 🙂

    Grüssli



  • @Dravere:
    Ja, stimmt schon.
    Bin ja selber auch ein riesen Sturschädel.

    Ich finds in diesem Fall halt wieder mal witzig. Th69 schreibt dass er was falsch macht, und du dann erklärst was.

    Statt sich bei Th69 zu beschweren, dass ihm die Aussage "du machst was falsch" ohne weitere Erklärung nix bringt, sagt er ihm aber (sinngemäss) "pah, ich mach schon alles richtig, du kennst dich bloss nix aus".
    Und schreibt dir dann im gleichen Atemzug, dass du Recht hattest. Recht mit einem Hinweis darauf, was er falsch macht.


  • Administrator

    hustbaer schrieb:

    Statt sich bei Th69 zu beschweren, dass ihm die Aussage "du machst was falsch" ohne weitere Erklärung nix bringt, sagt er ihm aber (sinngemäss) "pah, ich mach schon alles richtig, du kennst dich bloss nix aus".
    Und schreibt dir dann im gleichen Atemzug, dass du Recht hattest. Recht mit einem Hinweis darauf, was er falsch macht.

    Schon mal was von Trotz gehört? 😉
    Auch wenn du weisst, was trotzen ist, solltest du mal den Wikipedia Artikel durchlesen. Es passt nämlich hier ziemlich gut hin.

    Der Trotz empfindende und ausübende Mensch befindet sich dabei in einem Zustand des inneren, leicht auch äußeren Widerstandes gegen die menschliche Umwelt im Sinne der Selbstbehauptung. Es besteht immer auch eine latente Tendenz zum Abbruch der Kommunikation. In der Psychologie ist auch die komplexe Abwehrreaktion der Reaktanz beschrieben, die zum Beispiel dann eintritt, wenn eine Appellbotschaft auf der Beziehungsebene nicht fundiert ist.

    Grüssli



  • Klar weiss ich was Trotz ist.
    Es ist halt für aussenstehende trotzdem schwer begraifbar, wenn dabei etwas so offensichtlich widersprüchliches rauskommt.
    Auch wenn sie selbst manchmal genau so reagieren.


Log in to reply