Neuzeichnen von Steuerelementen zeitweise unterbinden

Veröffentlicht: 16. Apr 2003 | Aktualisiert: 22. Jun 2004

Von Mathias Schiffer

Die Microsoft Newsgroups sind eine Quelle schier unerschöpflichen Wissens, das nahezu auf Knopfdruck abrufbar ist: Hunderte deutschsprachige Entwickler vom Einsteiger bis zum Profi treffen sich hier täglich virtuell, um Fragen zu stellen oder zu beantworten. Auch themennahe Probleme, Ansichten und Konzepte werden miteinander diskutiert. Sie kennen die Microsoft Newsgroups noch nicht? Detaillierte Information für Ihre Teilnahme finden Sie auf der Homepage der Microsoft Support Newsgroups.

Diese Kolumne greift regelmäßig ein besonders interessantes oder häufig nachgefragtes Thema aus einer der Entwickler-Newsgroups auf und arbeitet es aus.

Aus der Visual Basic Newsgroup microsoft.public.de.vb:

Ich habe eine Klasse geschrieben, welche mir verschiedene Formate in ein TreeView-Steuerelement einliest. Mein TreeView-Objekt übergebe ich an diese Klasse.

Leider wird nun bei jeder Erweiterung des Steuerelements dieses im Formular aktualisiert, was natürlich ernorm viel Zeit kostet. Wie kann ich es erreichen, dass es z.B. nur nach jeweils 100 neuen Einträgen aktualisiert wird?

Das Problem des wiederholten Neuzeichnens bei vielen hinzuzufügenden Elementen betrifft diverse Steuerelemente - am auffälligsten zeigt es sich jedoch bei den "Microsoft Windows Common Controls"-Steuerelementen TreeView und ListView, die aus modernen Benutzeroberflächen nicht mehr wegzudenken sind.

Die einfachste Variante: Steuerelement ausblenden
Sie können verschiedene Strategien verfolgen, um die Auswirkungen dieses Problems zu umgehen. Der einfachste Weg ist der offensichtliche: Blenden Sie das Steuerelement während der Aktualisierung über seine Visible-Eigenschaft aus, entfällt die Notwendigkeit der Aktualisierung. Belohnt wird diese Aktion zwar mit einer schnelleren Abarbeitung, jedoch flackert dafür das gesamte Steuerelement durch das Aus- und Einblenden einmalig.

Ein weiterer offensichtlicher Nachteil: Je mehr Einträge Sie hinzufügen, desto länger bleibt das Steuerelement gänzlich unsichtbar - nicht gerade die Zierde einer Benutzeroberfläche. Daher empfiehlt es sich beim Verfolgen dieser einfachsten Methode, ein anderes Steuerelement gleicher Ausmaße und Gestalt hinter das ListView- bzw. TreeView-Control zu legen, bevor dieses ausgeblendet wird. Ressourcenschonend eignet sich hierfür etwa ein Label-Steuerelement mit entsprechend gesetzten Eigenschaften. Natürlich ist diese Illusion nicht perfekt - sie bietet dennoch eine schnelle und unkomplizierte Abhilfe an.

' Einfachste Variante, das Flackern im 
' TreeView/ListView zu verhindern: Ausblenden 
' des Controls mit Anzeige eines Labels. 
' Beispiel: Form1 mit TreeView1, Label1 und Command1 
Option Explicit 
Private Sub Form_Load() 
  ' Das Label-Steuerelement anpassen und hinter 
  ' dem TreeView-Steuerelement platzieren: 
  With Label1 
 .Caption = vbNullString 
 .Appearance = 1 
 .BorderStyle = 1 
 .BackColor = vbWhite 
 .Move TreeView1.Left, _ 
 TreeView1.Top, _ 
 TreeView1.Width, _ 
 TreeView1.Height 
 .ZOrder 
 .Visible = True 
  End With 
  Command1.Caption = "Einträge hinzufügen" 
End Sub 
Private Sub Command1_Click() 
Dim i As Long 
  ' TreeView-Control ausblenden (Label1 wird sichtbar) 
  TreeView1.Visible = False 
  ' 5.000 neue Nodes anlagen 
  With TreeView1.Nodes 
 For i = 1 To 5000 
   ' Einen neuen Node hinzufügen 
   .Add Text:="Eintrag Nr. " & CStr(i) 
   ' Benutzeroberfläche bedienbar halten: 
   If i Mod 100 = 0 Then 
  DoEvents 
   End If 
 Next i 
  End With 
  ' TreeView-Control wieder einblenden (Label1 wird überdeckt) 
  TreeView1.Visible = True 
End Sub

Fensteraktualisierung blockieren mit LockWindowUpdate
So simpel die erste Variante auch gewesen sein mag - als endgültige Lösung vermag sie nicht zu überzeugen: Selbst mit der Ersatzfläche, die das Label-Steuerelement für das ausgeblendete Control zur Verfügung stellt, ist dieser Ansatz kein optischer Leckerbissen. Gerade, wenn das auszublendende Steuerelement bereits Einträge enthielt, fällt die leere Ersatzfläche unschön ins Auge.

Eine geeignetere Alternative bietet sich mit dem Windows API an: Die Funktion LockWindowUpdate ermöglicht es, die Aktualisierung eines Fensters am Bildschirm zu unterdrücken. Als Parameter wird ihr dazu einfach das entsprechende Fensterhandle übergeben. Um die Blockade wieder aufzuheben, ist die Funktion mit dem Parameter 0 aufzurufen:

' Blockieren des Neuzeichnens eines Fensters 
' mithilfe der API-Funktion LockWindowUpdate 
' Beispiel: Form1 mit TreeView1 und Command1 
Option Explicit 
Private Declare Function LockWindowUpdate _ 
  Lib "user32" ( _ 
  ByVal hwndLock As Long _ 
  ) As Long 
Private Sub Form_Load() 
  Command1.Caption = "Einträge hinzufügen" 
End Sub 
Private Sub Command1_Click() 
Dim i As Long 
  ' Die Aktualisierung des TreeView-Fensters unterdrücken 
  LockWindowUpdate TreeView1.hWnd 
  ' 5.000 neue Nodes anlagen 
  With TreeView1.Nodes 
 For i = 1 To 5000 
   ' Einen neuen Node hinzufügen 
   .Add Text:="Eintrag Nr. " & CStr(i) 
   ' Nach jeder 100sten Aktualisierung die 
   ' Bildschirmanzeige auffrischen und die 
   ' Benutzeroberfläche bedienbar halten: 
   If i Mod 100 = 0 Then 
  LockWindowUpdate 0 
  LockWindowUpdate TreeView1.hWnd 
  DoEvents 
   End If 
 Next i 
  End With 
  ' Die Aktualisierung des TreeView-Fensters wieder zulassen 
  LockWindowUpdate 0 
End Sub

Auf diese Weise wird das TreeView-Fenster des Beispiels nur bei jeder einhundertsten Erweiterung um einen Eintrag am Bildschirm aktualisiert.