in einem meiner letzten Projekte durfte ich eine große Anwendung mit Winforms umsetzen. Es war eine Anwendung mit einer komplexen UI und einer Menge an Daten, welche strukturell sehr komplex aufgebaut waren. Mit einfachen Controls konnte man die Anforderungen nicht erfüllen, also musste man viele UserControls erstellen.
Nun kommt man in Winforms relativ schnell an den Punkt, dass wenn man mehrere UserControls auf einer UI hat, das man unschöne Paint-Artefakte bekommt. Das schlimmste dürfte schon vielen von euch begegnet sein: Flacken und Flimmern beim Anzeigen der Controls. Ich möchte euch hier meine Lösungen aufzeigen, jenachdem ob es sich um ein einzelnes Controls handelt, oder ob man mehrere UserControls in einem Panel anzeigen möchte (und hier das sichtbare Aufbauen der UserControls verhindern möchte).
- Flackern bei einzelnen UserControls vermeiden
Das Problem bei den Zeichenanforderungen in WinForms ist das sequentielle Zeichnen. Um dieses Vorgang vor dem Benutzer zu "verheimlichen" können wir uns dder Technik des DoubleBufferings bedienen. Winforms bietet dazu automatische Methoden um DoubleBuffering zu verwenden. Dazu müssen nur ein Paar Styles gesetzt werden.
Das setzen der Styles muss im Konstruktor des jeweiligen UserControls erfolgen, nach dem Aufruf von InitializeComponents()
Weitere Optimierungen kann man durch das Überschrieben von OnPaintBackground erreichen. Da in meinem Projekt das oberer ausgereicht hat, habe ich dafür kein Beispiel. Allerdings findet ihr hier weitere Beispiele. - Artefakte beim Hinzufügen mehrere UserControls zu einem Panel verhindern
- Oft kommt es auch zu unschönen visuellen Effekten, wenn man mehrere UserControls zu einem Panel, zB. TableLayoutPanel oder FlowLayoutPanel hinzufügen möchte. Das liegt daran, dass Winforms alle Controls hintereinander zeichnet und diesen Vorgang vor dem Benutzer nicht verbirgt. Das kann man allerdings erreichen, wenn man ein bisschen mit Windowsmessages arbeitet.
- Zuerst sollte man sich dazu eine Variable anlegen, welche der Message WM_SETREDRAW entspricht. Diese Message werden wir nämlich an und abschlaten. Wir bauen damit eine Methodik nach, die dem BeginUpdate() und EndUpdate() von ListViews entspricht.
- Dann benötigen wir eine Methode, welche die Messages auf einem Control verändert. Ich habe diese Methoden als Extensions implementiert:
- Und natürlich eine Methode, welche nach der Arbeit die Messages wieder aktiviert:
- Um nun die Artefakte zu verhindern, wenn man viele UserControls einem TableLayoutPanel hinzuzufügen, sollte man SuspendMessage und SuspendLayout auf dem Panel aufrufen, bevor man die Controls hinzufügt. Dafür habe ich mir auch noch eine Extension geschrieben:
Natürlich benötigen wir noch eine Methode um alles wieder zu aktivieren:
Wenn man dann UserControls hinzufügen möchte, sollte man das hinzufügen zwischen die Aufrufe setzen:
Ich hoffe ich konnte euch damit etwas helfen :)
mfg
Sebastian







Keine Kommentare:
Kommentar veröffentlichen