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
}
}
}
}
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.
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.
wie geschrieben; sind die items der listbox gecached im ondrawitem werden nurnoch 2 bilder (1 selection) gezeichnet..
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
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?
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 ^^
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.
sry war auf ner tagung unterwegs hatte kaum zeit..
achso, ja gut jetzt hats klick gemacht... das werd ich mal versuchen, danke ^^