none
OnMouseHover dauert zu lange RRS feed

  • Frage

  • Hallo allerseits,

    hätte da eine Frage bzgl. Controls.MouseHover da ich hier eine kleine Zeitverzörung merke.
    In einer kleinen Form erstelle ich Dyn. Buttons.

    foreach (string tb in Auflistung) { Button btn = new Button(); this.Controls.Add(btn);
    ... btn.MouseHover += btn_MouseHover; btn.MouseLeave += btn_MouseLeave; btn.Click += btn_Click; usw. und so fort ...

    void btn_MouseHover(object sender, EventArgs e) { Button btn = sender as Button; btn.Size = new Size(btn.Width + 10, btn.Height + 10); btn.Location = new Point(btn.Location.X - 5, btn.Location.Y - 5); }

    In der OnMouseOver Methode hebe ich den Button hervor in dem die Größe und Position geändert wird.
    In der MouseLeave wird das ganze wieder zurückgesetzt.
    Doch wenn der Mauszeiger über einen der Buttons ist dann dauert das kurz bis das hervorgehoben ist.

    Wieso gibt es hier eine Zeitverzögerung, das kann doch nicht vom Cast und der bisschen Berechnung sein?


    Danke im voraus und Lg
    String.Rise
    Donnerstag, 28. November 2013 16:35

Antworten

  • Hallo,

    Du solltest zuerst einmal gucken, was da noch an Ereignissen stattfindet. Ein Zucken oder eine Verzögerung kann ich (bei ansonsten eher ereignisfreiem Formular) nicht feststellen:

            Rectangle buttonBounds = Rectangle.Empty;
    
            void Button_MouseHover(object sender, EventArgs e)
            {
                Debug.WriteLine("Button_MouseHover");
                var control = (Control)sender;
                if (buttonBounds == Rectangle.Empty)
                {
                    this.buttonBounds = control.Bounds;
                    control.Bounds = new Rectangle(buttonBounds.X - 5, buttonBounds.Y - 5, buttonBounds.Width + 10, buttonBounds.Height + 10);
                }
            }
    
            void Button_MouseLeave(object sender, EventArgs e)
            {
                Debug.WriteLine("Button_MouseLeave");
                var control = (Control)sender;
                if (buttonBounds != Rectangle.Empty)
                {
                    control.Bounds = this.buttonBounds;
                    this.buttonBounds = Rectangle.Empty;
                }
            }
    

    An den ControlStyles sollte man erst gezielt drehen, wenn man die Verursacher kennt und sich es anders nicht lösen lässt.

    DoubleBuffer wirkt für den obigen Code sowieso kaum, da das Steuerelement definitiv neu gezeichnet werden muss und wäre nicht auf Steuerelement-Ebene, sondern für den Container (Form etc.) zu setzen, da dessen Hintergrund durch die Größenänderung beeinflusst wird.

    Gruss Elmar

    • Als Antwort markiert String.Rise Mittwoch, 11. Dezember 2013 07:10
    Freitag, 29. November 2013 08:07
    Beantworter

Alle Antworten

  • Hallo,

    das liegt nicht so sehr am Code, als vielmehr daran, dass das Steuerelement neu gezeichnet werden muss[1]. Paint-Ereignisse kommen erst am Ende, wenn nichts anderes mehr zu tun ist.

    Etwas beschleunigen kannst Du es im obigen Falle, in dem Du die Bounds Eigenschaft verwendest, denn so wird nur eine Nachricht an das Steuerelement zur Anpassung gesendet, ansonsten erzeugen Size und Location zwei davon (und die gehen intern wieder über Bounds).

    Gruß Elmar

    [1] Befindet sich das Steuerelement in einem Container (z. B. TableLayoutPanel), so kann das Berechnen des Layout für andere Steuerlemente ebenfalls Zeit beanspruchen.

    Donnerstag, 28. November 2013 17:07
    Beantworter
  • Hallo Elmar,

    danke für den hinweis.
    Merkbar ist der Unterschiedlich nicht wirklich.

    Kann man das nicht so irgendwie Double-Buffering oder ähnlich bewärkstelligen.
    Bsp:

    this.DoubleBuffered = true;
    this.SetStyle(ControlStyles.UserPaint | 
                  ControlStyles.AllPaintingInWmPaint |
                  ControlStyles.ResizeRedraw |
                  ControlStyles.ContainerControl |
                  ControlStyles.OptimizedDoubleBuffer |
                  ControlStyles.SupportsTransparentBackColor
                  , true);
    Wobei das mehr dazu dient das flimmern zu unterdrücken?


    Lg


    Freitag, 29. November 2013 07:05
  • Hallo,

    Du solltest zuerst einmal gucken, was da noch an Ereignissen stattfindet. Ein Zucken oder eine Verzögerung kann ich (bei ansonsten eher ereignisfreiem Formular) nicht feststellen:

            Rectangle buttonBounds = Rectangle.Empty;
    
            void Button_MouseHover(object sender, EventArgs e)
            {
                Debug.WriteLine("Button_MouseHover");
                var control = (Control)sender;
                if (buttonBounds == Rectangle.Empty)
                {
                    this.buttonBounds = control.Bounds;
                    control.Bounds = new Rectangle(buttonBounds.X - 5, buttonBounds.Y - 5, buttonBounds.Width + 10, buttonBounds.Height + 10);
                }
            }
    
            void Button_MouseLeave(object sender, EventArgs e)
            {
                Debug.WriteLine("Button_MouseLeave");
                var control = (Control)sender;
                if (buttonBounds != Rectangle.Empty)
                {
                    control.Bounds = this.buttonBounds;
                    this.buttonBounds = Rectangle.Empty;
                }
            }
    

    An den ControlStyles sollte man erst gezielt drehen, wenn man die Verursacher kennt und sich es anders nicht lösen lässt.

    DoubleBuffer wirkt für den obigen Code sowieso kaum, da das Steuerelement definitiv neu gezeichnet werden muss und wäre nicht auf Steuerelement-Ebene, sondern für den Container (Form etc.) zu setzen, da dessen Hintergrund durch die Größenänderung beeinflusst wird.

    Gruss Elmar

    • Als Antwort markiert String.Rise Mittwoch, 11. Dezember 2013 07:10
    Freitag, 29. November 2013 08:07
    Beantworter