Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Flackern beim Laden von UserControls verhindern

51 views
Skip to first unread message

Thomas Meutzner

unread,
Mar 10, 2009, 3:18:06 AM3/10/09
to
Hallo,
ich habe eine WinForms Anwendung mit C#2008 und unter Verwendung des
Framework 3.5 erstellt.
Diese Anwendung besitzt links einen Navigationsbereich und rechts der
Arbeitsbereich, der je nach angeklickten Menüpunkt unterschiedliche
Daten darstellt. In der Regel ist der Arbeitsbereich in einen
Tabellenansicht (oben) und eine Detailansicht (unten, dient als
Vorschau) aufgeteilt. Zum Einsatz kommen neben den WinForms Controls
auch die Janus WinForms Controls.

Die Formulare für den Arbeitsbereich habe ich als UserControls
erstellt. Diese UserControls füllen den rechten Bereich komplett aus
(Dock=Fill). Im Vorschaubereich sind viele Controls enthalten, die als
Hintergrundfarbe Transparent verwenden und die sich teilweise in
Groupboxen befinden. In den Load-Ereignissen werden die entsprechenden
Daten aus der Datenbank geholt und an die Elemente gebunden.
Alle UserControls für den Arbeitsbereich sind von einem
"Haupt-UserControl" abgeleitet, welches verschiedene Eigenschaften und
Methoden zur Verfügung stellt, die ich überschreiben kann. Das
ansteuern und Anzeigen der UserControls aus dem Hauptprogramm erfolgt
so:
- Prüfung welches Control geladen werden soll
- Bildung einer neuen Instanz des Controls
- Unsichtbar setzen des Controls
- Setzen der verschiedenen Eigenschaften (z.B. DataSource, aktueller
Benutzer etc.)
- Einbindung in den rechten Bereich des Hautprogrammes
- Anzeige des Controls

Ich habe das Problem, dass man beim Laden der UserControls ein
Flackern sieht. Um dies zu verhindern habe ich bei jedem UserControl
im Konstruktor SetStyle gesetzt:
this.DoubleBuffered = true;
this.SetStyle(ControlStyles.OptimizedDoubleBuffer |
ControlStyles.AllPaintingInWmPaint |
ControlStyles.UserPaint, true);

Im Konstruktor und im Load-Ereignis wurden außerdem vor und nach den
aufgerufenen Methoden this.SuspendLayout() und this.ResumeLayout()
implementiert.
Dies führte zu keiner sichtbaren Reduktion des Flackerns. Auch das
setzen von Visible=false nach dem Instanzieren des Controls brachte
keine Besserung.
Danach habe ich in den Quellcode des Controls CreateParams
überschrieben.
protected override CreateParams CreateParams
{
get
{
CreateParams result = base.CreateParams;
result.ExStyle |= 0x02000000; // WS_EX_COMPOSITED
return result;
}
}

Jetzt flackert es weniger, aber dafür habe ich zwei neue
Erscheinungen:
1. Bei einigen verschachtelten Controls die Hintergrundfarbe nicht
mehr transparent angezeigt, sondern diese ist weiß.
2. Wenn ich einen Dialog über meine Anwendung lege und diesen mit der
Maus verschiebe, erhalte ich Schlieren auf dem Bildschirm.

Wie geht Ihr bei komplexen Layouts vor, um das Flackern zu
unterbinden?
Vielen Dank.
Thomas Meutzner

Carsten Unterberg

unread,
Mar 10, 2009, 3:34:27 AM3/10/09
to
Hallo Thomas,

"Thomas Meutzner" <Thomas....@tmeutzner.net> schrieb im Newsbeitrag
news:di4cr4ps1h1doo9ku...@4ax.com...

da das WinForms-Modell auf GDI(+) basiert und GDI(+) nicht unbedingt für
graphische Anwendungen taut, ist hier die Leistungsfähigheit schnell
ausgeschöpft. Gerade wenn es um solche Dinge wie Transparenzen und
ineinander geschachtelte Steuerelemente geht passiert dies sehr schnell.
Wenn Dir soviel am flackern liegt (ich weiß, dass es nicht schön aussieht),
solltest Du vielleicht auf WPF umsteigen.

MfG

Carsten Unterberg | Test-Framework
http://test-framework.blogspot.com/


Frank Dzaebel

unread,
Mar 10, 2009, 3:33:30 PM3/10/09
to
Hallo Thomas,

> Ich habe das Problem, dass man beim Laden der UserControls ein
> Flackern sieht. Um dies zu verhindern habe ich bei jedem UserControl
> im Konstruktor SetStyle gesetzt:
> this.DoubleBuffered = true;
> this.SetStyle(ControlStyles.OptimizedDoubleBuffer |
> ControlStyles.AllPaintingInWmPaint |
> ControlStyles.UserPaint, true);

ja, das ist schon ein guter Anfang, aber,
da fehlt für Dein Beispiel auch noch:
- SupportsTransparentBackColor und
- ContainerControl:

[Gewusst wie: Verwenden eines transparenten Hintergrunds für ein
Steuerelement]
http://msdn.microsoft.com/de-de/library/wk5b13s4.aspx

[ControlStyles-Enumeration (System.Windows.Forms)]
http://msdn.microsoft.com/de-de/library/system.windows.forms.controlstyles.aspx
______

Zusätzlich noch OnPaintBackground überschreiben
(und nichts darin ausführen) :

[Double buffering Windows Forms]
http://www.bobpowell.net/doublebuffer.htm
______

Zusätzlich sollte man bei DoubleBuffering auch
wirklich alles im OnPaint ausführen.
______

WS_EX_COMPOSITED wird zwar zum Teil zur
Behebung des Child-Control Flackerns (in UserControls)
benutzt, aber führt in einigen Fällen 100% CPU Last.

Erstmal so die Standards ...


ciao Frank
--
Dipl.Inf. Frank Dzaebel [MCP/MVP C#]
http://Dzaebel.NET

Thomas Meutzner

unread,
Mar 11, 2009, 6:23:41 AM3/11/09
to
On Tue, 10 Mar 2009 20:33:30 +0100, "Frank Dzaebel"
<Po...@FranksSeite.de> wrote:
>Zusätzlich noch OnPaintBackground überschreiben
>(und nichts darin ausführen) :
>
>[Double buffering Windows Forms]
>http://www.bobpowell.net/doublebuffer.htm
>______
>
>Zusätzlich sollte man bei DoubleBuffering auch
>wirklich alles im OnPaint ausführen.
>______
>
>WS_EX_COMPOSITED wird zwar zum Teil zur
>Behebung des Child-Control Flackerns (in UserControls)
>benutzt, aber führt in einigen Fällen 100% CPU Last.
>
>Erstmal so die Standards ...
>
>
>ciao Frank

Hallo Frank,

erstmal vielen Dank für Deine Antwort. Ich habe die SetStyle Methode
noch um die zwei Werte erweitert. Das habe ich auch bei den "Master"
Control gemacht, von dem die anderen Controls abgeleitet sind. Bis
jetzt hat es bei mir noch nicht den gewünschten Effekt gebracht.
Dann habe ich das Laden bzw. das Füllen der Daten in die
Steuerelemente in OnPaint eingebunden. Dabei habe ich aber das
Problem, das OnPaint nicht angesprungen wird. Habe ich irgendetwas
dabei vergessen?
Gruß
Thomas

Diana Bulthaupt

unread,
Apr 20, 2009, 10:24:05 AM4/20/09
to
> Dabei habe ich aber das
> Problem, das OnPaint nicht angesprungen wird. Habe ich irgendetwas
> dabei vergessen?
> Gruß
> Thomas
>

Vermutlich hast Du private void OnPaint(object sender, PaintEventArgs e)
verwendet. Leg eine OnPaint mit diesem Prototyping an:
protected override void OnPaint(PaintEventArgs e)

0 new messages