Laden...

OwnerDrawFixed ListBox: selektierte Item flackert

Erstellt von KainPlan vor 14 Jahren Letzter Beitrag vor 11 Jahren 2.530 Views
K
KainPlan Themenstarter:in
133 Beiträge seit 2009
vor 14 Jahren
OwnerDrawFixed ListBox: selektierte Item flackert

Hi Leute,

ich hab eine Listbox in deren OnDrawItem-Ereigniss ich die Items zeichne. Soweit so gut, nur ist mir aufgefallen, dass das selektierte Item, wärend der Laufzeit, flackert. Sehr gut zu beobachten ist dies wenn ganz nach unten scrollt und man nicht mehr weiter scrollen kann das selektierte Item noch sichtbar ist und trozdem weiter nach unten scrollt (mit dem Mausrad). AllPaintingInWmPaint ist gesetzt und OptimizedDoubleBuffer auch. Kann jemand dieses Verhalten bestätigen? Hat das jemand vllt schon beobachtet? Ist da vllt was zu machen?

Hier mal ein grobes Beispiel:



        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            Pen p = new Pen(Color.Transparent);
            SolidBrush b = new SolidBrush(Color.Transparent);

            Graphics dc = e.Graphics;
            dc.CompositingQuality = CompositingQuality.HighSpeed;
            dc.InterpolationMode = InterpolationMode.HighQualityBicubic;
            dc.SmoothingMode = SmoothingMode.HighQuality;
            dc.SetColorTableWindowsVista(_clTable);

            dc.FillRectangle(new SolidBrush(BackColor), e.Bounds);
            dc.DrawVistaButtonBackground(e.Bounds, 2, 
                true, 
                false,
                (e.State & DrawItemState.Selected) == DrawItemState.Selected
                /*(e.State & DrawItemState.Focus)    == DrawItemState.Focus*/);

            FileData fd = null;
            if (e.Index > -1 && e.Index < Items.Count)
                fd = Items[e.Index] as FileData;
            if (fd != null)
            {
                if (fd.FileIco != null)
                    dc.DrawIcon(fd.FileIco, new Rectangle(e.Bounds.Left + 2, e.Bounds.Top + 2, 35, 35));

                SizeF sz = dc.MeasureString(fd.FileName, e.Font);
                RectangleF rc = new RectangleF(
                    e.Bounds.Left + 37,
                    e.Bounds.Top + 5,
                    e.Bounds.Width - 5,
                    sz.Height);
                StringFormat sf = new StringFormat();
                sf.FormatFlags = StringFormatFlags.NoWrap;
                sf.Trimming = StringTrimming.EllipsisCharacter;
                dc.DrawString(fd.FileName, e.Font, Brushes.White, rc, sf);


                sz = dc.MeasureString(fd.FileName, e.Font);
                rc = new RectangleF(
                    e.Bounds.Left + 37,
                    e.Bounds.Bottom - sz.Height + 2,
                    e.Bounds.Width - 40,
                    sz.Height);
                sf = new StringFormat();
                sf.FormatFlags = StringFormatFlags.NoWrap;
                sf.Trimming = StringTrimming.EllipsisPath;
                dc.DrawString(fd.File, new Font(e.Font.FontFamily, 6), new SolidBrush(Color.FromArgb(100, 255, 255, 255)),
                     rc, sf);
            }
        }

C
18 Beiträge seit 2009
vor 14 Jahren

Hi KaiPlain,

ich denke mal das du dir ein eigenes Steuerelement geschrieben hast. Hier musst du nämlich die Double-Buffer-Technik einsetzen die bei einer PictureBox schon standartmäßig aktiv ist.

Grüße

49.485 Beiträge seit 2005
vor 14 Jahren

Hallo Chrisi,

Hier musst du nämlich die Double-Buffer-Technik einsetzen

hat KainPlan ja schon.

Hallo KainPlan,

vielleicht hilft aber einer der anderen Tipps aus [FAQ] Flackernde Controls vermeiden / Schnelles, flackerfreies Zeichnen.

herbivore

K
KainPlan Themenstarter:in
133 Beiträge seit 2009
vor 14 Jahren

Da hab ich natürlich schon reingeguckt. Es flackert auch nur das selektierte Item alles andere wird komplett "flüssig" gezeichnet. Man sieht das auch seh schön wenn man einfach Arrow-Down gedrückt hält wärend die LB den fokus hat... ich teste das jetzt gleich mal an einer anderen LB.

2.891 Beiträge seit 2004
vor 11 Jahren

Sehr gut zu beobachten ist dies wenn ganz nach unten scrollt und man nicht mehr weiter scrollen kann das selektierte Item noch sichtbar ist und trozdem weiter nach unten scrollt (mit dem Mausrad)

Das kann ich bestätigen. Und das DoubleBuffering des Controls selbst bringt nichts.
Da ich das Problem gerade auch habe, hier meine Lösung: BufferedGraphics.


protected override void OnDrawItem(DrawItemEventArgs e)
{
	using (BufferedGraphics bufferedGraphics = BufferedGraphicsManager.Current.Allocate(e.Graphics,e.Bounds))
	using (Graphics graphics = bufferedGraphics.Graphics)
	{
		// Achtung: Zeichenbereich verschiebt sich
		Rectangle bounds = new Rectangle(0,0,e.Bounds.Width,e.Bounds.Height);

		// entspricht e.DrawBackground()
		using (Brush brush = new SolidBrush(e.BackColor))
			graphics.FillRectangle(brush,e.Bounds);

		// entspricht e.DrawFocusRectangle()
		if (e.State.HasFlag(DrawItemState.Focus) && !e.State.HasFlag(DrawItemState.NoFocusRect))
			ControlPaint.DrawFocusRectangle(graphics,e.Bounds,this.ForeColor,this.BackColor);

		// Checkbox zeichnen (Achtung: Zum Platzieren die ursprünglichen e.Bounds verwenden)
		CheckState checkState = this.GetItemCheckState(e.Index);
		CheckBoxState checkBoxState = (checkState==CheckState.Checked) ? CheckBoxState.CheckedNormal : (checkState==CheckState.Unchecked) ? CheckBoxState.UncheckedNormal : CheckBoxState.MixedNormal;
		Size glyphSize = CheckBoxRenderer.GetGlyphSize(graphics,checkBoxState);
		CheckBoxRenderer.DrawCheckBox(graphics,new Point(e.Bounds.X+this.Margin.Left,e.Bounds.Y+(e.Bounds.Height-glyphSize.Height)/2),checkBoxState);

		// Text
		TextRenderer.DrawText(graphics,...


		// alles auf einmal in e.Graphics übertragen
		bufferedGraphics.Render();
	}
}