Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
OwnerDrawn ListBox abgewählte Item flackert
KainPlan
myCSharp.de - Member



Dabei seit:
Beiträge: 133
Herkunft: Gelsenkirchen

Themenstarter:

OwnerDrawn ListBox abgewählte Item flackert

beantworten | zitieren | melden

Hallo,

ich hatte mich einige zeit zur Ruhe gesetzt und bin wieder ein bisschen am Programmieren ;) zu meinem Problem:

jedesmal wenn ich in meiner ListBox ein Item abwähle, sprich wenn ich ein anderes Item neu Selektiere, flackert das abgewählte item. Ich hab echt alles versucht überall rum gegooglet aber ich habe keine Ahnung was da passiert und warum es flackert. :(


Wen es interessiert hier mal ein Bld vom Projekt (und der ListBox): siehe Anhang

Hier mal der code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;

using DrawingEx;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace substx
{
    class DesignListBox : ListBox
    {
        public DesignListBox()
        {
            base.SetStyle(ControlStyles.OptimizedDoubleBuffer |
                          ControlStyles.ResizeRedraw |
                          ControlStyles.AllPaintingInWmPaint,
                          true);

            // DoubleBuffered = true; <-- nutzt auch nix WAH!!!
            base.DrawMode = DrawMode.OwnerDrawFixed;
        }

        protected override void OnDrawItem(DrawItemEventArgs e)
        {

            Rectangle bnd = e.Bounds;
            Graphics dc = e.Graphics;
            ColorTable ct = (ColorTable)Items[e.Index];
            int pad = 6;
            int pwh = bnd.Height - 2 * pad;
            Rectangle pi0 = new Rectangle(bnd.X + pad, bnd.Y + pad, pwh, pwh);
            Rectangle pi1 = new Rectangle(bnd.X + pi0.Right + pad, bnd.Y + pad, pwh, pwh);
            Rectangle pi2 = new Rectangle(bnd.X + pi1.Right + pad, bnd.Y + pad, pwh, pwh);
            Rectangle pi3 = new Rectangle(bnd.X + pi2.Right + pad, bnd.Y + pad, pwh, pwh);

            if (ct == null)
            {
                #region Error
                dc.FillRectangle(new SolidBrush(BackColor), bnd);
                StringFormat sf = new StringFormat();
                sf.LineAlignment = StringAlignment.Center;
                sf.Alignment = StringAlignment.Center;
                dc.DrawString("Error Item.", Font, new SolidBrush(Color.Red), bnd, sf);
                #endregion
            }
            else
            {
                #region Preview
                dc.SetColorTableWindowsVista(ct);
                dc.FillRectangle(new SolidBrush(ct.Background), bnd);
                dc.DrawVistaButtonBackground(pi0, 2, true, false, false);
                dc.DrawVistaButtonBackground(pi1, 2, true, true, false);
                dc.DrawVistaButtonBackground(pi2, 2, true, false, true);
                dc.DrawVistaButtonBackground(pi3, 2, true, true, true);

                Rectangle capt = bnd; capt.X += 8; capt.Width -= 8;
                StringFormat sf = new StringFormat();
                sf.LineAlignment = StringAlignment.Center;
                dc.DrawString(ct.Name + ((ct == Design.ColorTable) ? " (Aktiv)" : ""), Font, new SolidBrush(ct.Text), capt, sf);
                #endregion
            }

            if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
            {
                #region Selection
                Rectangle sel = bnd;
                Rectangle selhalf;
                Color selcl = Color.CornflowerBlue;

                sel.Inflate(-2, -2);
                using (GraphicsPath psel = RoundedRectangle.Create(sel, 2))
                {
                    using (Pen selouter = new Pen(Color.FromArgb(75, selcl)))
                    {
                        dc.DrawPath(selouter, psel);
                    }
                }
                sel.Inflate(-1, -1);
                selhalf = sel;
                selhalf.Height /= 2;
                using (GraphicsPath psel = RoundedRectangle.Create(selhalf, 2,
                    RoundedRectangle.RectangleCorners.TopLeft &
                    RoundedRectangle.RectangleCorners.TopRight))
                {
                    selhalf.Height++;
                    using (LinearGradientBrush lgb = new LinearGradientBrush(
                        selhalf, Color.FromArgb(150, selcl), Color.Transparent, 90f))
                    {
                        dc.FillPath(lgb, psel);
                    }
                }
                using (GraphicsPath psel = RoundedRectangle.Create(sel, 2))
                using (Pen selinner = new Pen(Color.FromArgb(150, selcl)))
                {
                    dc.DrawPath(selinner, psel);
                }
                #endregion
            }
        }
    }
}


Attachments
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo KainPlan,

siehe [Artikel] Flackernde Controls und flackerndes Zeichnen vermeiden.

herbivore
private Nachricht | Beiträge des Benutzers
KainPlan
myCSharp.de - Member



Dabei seit:
Beiträge: 133
Herkunft: Gelsenkirchen

Themenstarter:

beantworten | zitieren | melden

Der Thread hat mich auch nicht weiter gebracht. Hab nun für die Items einen cache angelegt das verbessert das flackern ein wenig aber entfernt es auch nicht komplett.
private Nachricht | Beiträge des Benutzers
winSharp93
myCSharp.de - Experte

Avatar #avatar-2918.png


Dabei seit:
Beiträge: 5.742
Herkunft: Stuttgart

beantworten | zitieren | melden

Hallo KainPlan,

evtl. kommt noch eine Zeichenroutine für den Hintergrund daziwschen.

Was eigentlich immer gegen Flackern hilft: How do I suspend painting for a control and its children? (ist dann allerdings die "Holzhammervariante").
Aber ein Tipp: Bei Darstellungsproblemen immer zunächst an der Stelle nach der Ursache suchen

BTW: Du solltest ein wenig sorgfältiger mit Brushes etc. umgehen - diese bei jedem Aufruf von Paint neu zu erzeugen, ist jedenfalls keine gute Idee - cache sie besser in Membervariablen, z.B. nach folgendem Muster:


private Brush _myBrush;

private Brush MyBrush
{
  get
  {
    if (this._myBrush == null)
      this._myBrush = this.CreateMyBrush();

      return this._myBrush;
  }
}

//Bei Änderungen aufrufen
private void ResetMyBrush()
{
  if (this._myBrush != null)
    this._myBrush.Dispose();
  this._myBrush = null;
}
private Brush CreateMyBrush()
{
   return new SolidColorBrush(this.MyColor);
}
Evtl. löst du schon dadurch das Problem, weil das Zeichnen so extrem beschleunigt werden sollte.
private Nachricht | Beiträge des Benutzers
KainPlan
myCSharp.de - Member



Dabei seit:
Beiträge: 133
Herkunft: Gelsenkirchen

Themenstarter:

beantworten | zitieren | melden

wie geschrieben; sind die items der listbox gecached im ondrawitem werden nurnoch 2 bilder (1 selection) gezeichnet..
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 49.486
Herkunft: Berlin

beantworten | zitieren | melden

Hallo KainPlan,

welche Wirkung AllPaintingInWmPaint bei OwnerDraw hat, ist mir nicht ganz klar. Immerhin zeichnest du ja gar nicht im WmPaint, sondern im OnDrawItem. Davon abgesehen könnte es nötig sein, dort zuerst base.OnDrawItem auszurufen.

herbivore
private Nachricht | Beiträge des Benutzers
winSharp93
myCSharp.de - Experte

Avatar #avatar-2918.png


Dabei seit:
Beiträge: 5.742
Herkunft: Stuttgart

beantworten | zitieren | melden

Zitat von KainPlan
wie geschrieben; sind die items der listbox gecached im ondrawitem werden nurnoch 2 bilder (1 selection) gezeichnet..
Wie ist das jetzt aufzufassen?
Hast du dir den Link mal angeschaut?
private Nachricht | Beiträge des Benutzers
KainPlan
myCSharp.de - Member



Dabei seit:
Beiträge: 133
Herkunft: Gelsenkirchen

Themenstarter:

beantworten | zitieren | melden

Die OnDrawItem methode Zeichnet ausschließlich zwischengespeicherte Bilder.

-->

if (selected)
    dc.DrawImage(selectedImages[idx])
else
    dc.DrawImage(itemImages[idx])

nichts anderes wird in der OnDrawItem methode getan. :)

versteh auch nicht ganz was der link mir bringen soll sry ^^
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von KainPlan am .
private Nachricht | Beiträge des Benutzers
winSharp93
myCSharp.de - Experte

Avatar #avatar-2918.png


Dabei seit:
Beiträge: 5.742
Herkunft: Stuttgart

beantworten | zitieren | melden

Zitat von KainPlan
versteh auch nicht ganz was der link mir bringen soll
Damit kannst du das Zeichnen eines Controls kurzzeitig komplett unterbinden.
Wenn du das während der Selektion durchführst, kannst du so evtl. das Flackern verhindern.
private Nachricht | Beiträge des Benutzers
KainPlan
myCSharp.de - Member



Dabei seit:
Beiträge: 133
Herkunft: Gelsenkirchen

Themenstarter:

beantworten | zitieren | melden

sry war auf ner tagung unterwegs hatte kaum zeit..
achso, ja gut jetzt hats klick gemacht... das werd ich mal versuchen, danke ^^
private Nachricht | Beiträge des Benutzers