Eine der Funktionen, die der VCL-Bibliothek in Delphi 11 hinzugefügt wurden, ist die Möglichkeit, die Windows-Meldung WM_SETREDRAW einfach mit zwei spezifischen Methoden zu verarbeiten, die der TWinControl-Klasse hinzugefügt wurden: LockDrawing und UnlockDrawing
Anfang dieser Woche ging ich meine To-do-Liste durch und fand einen Hinweis darauf, dass ich dem Blog-Beitrag zu neuen VCL-Funktionen in Delphi und C++Builder 11 über LockDrawing nachgehen sollte. Tatsächlich schrieb ich: „Die TWinControl-Basisklasse bietet jetzt LockDrawing- und UnlockDrawing-Methoden, um die Aktualisierung zu deaktivieren und zu steuern. Dies löst die Ausführung der Windows-Nachricht WM_SETREDRAW aus. Das ist wahrscheinlich einen eigenen Blogbeitrag wert… “, aber dann habe ich das total vergessen. Hier also der Blogpost, mit ein paar Monaten Verspätung.
Beginnen wir mit der Windows-API. Die Nachricht WM_SETREDRAW wird an ein Fenster gesendet, um zuzulassen, dass Änderungen in diesem Fenster neu gezeichnet werden, oder um zu verhindern, dass Änderungen in diesem Fenster neu gezeichnet werden. „Jedes Mal, wenn Sie eine Reihe von Vorgängen ausführen müssen, die alle neu gezeichnet werden müssen, können Sie sie anhalten und erst am Ende neu zeichnen, um ein Flackern zu vermeiden und den Prozess zu beschleunigen. Es ist natürlich wichtig, die Sperre zu entfernen und dann eine spezielle Funktion aufzurufen, um das Neuzeichnen zu erzwingen (RedrawWindow).
All dies ist ordnungsgemäß in zwei TWinControl-Methoden gekapselt, die der VCL-Bibliothek in RAD Studio 11 hinzugefügt wurden, LockDrawing und UnlockDrawing, die die WM_SETREDRAW-Nachricht mit den richtigen Parametern senden. Sie implementieren auch eine „Lock-Count-Logik“, sodass Sie, wenn Sie dasselbe Steuerelement zweimal sperren, es zweimal entsperren müssen, um mit dem Malen fortzufahren. Außerdem ruft UnlockDrawing automatisch die RedrawWindow-API auf.
Abgesehen davon, was sind die Anwendungsfälle? Ich habe eine Demo geschrieben, die zwei Szenarien zeigt, und Sie können sich auch diesen netten Blogbeitrag von Radek Cervinka ansehen.
Ein erster Fall in meiner Demo ist das Hinzufügen einer Reihe von Elementen zu einem Listenfeld. Während Delphi traditionell die Möglichkeit bot und immer noch hat, das Neuzeichnen zu vermeiden, indem die Aktualisierung der Zeichenfolgenliste „eingefroren“ wird, ist es sinnvoll, stattdessen das Neuzeichnen der Benutzeroberfläche zu sperren. Dies sind die beiden alternativen Codierungsstile:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
var I: Integer; begin ListBox1.Items.BeginUpdate; try for I := 1 to 10000 do ListBox1.Items.Add('Line ' + I.ToString); finally ListBox1.Items.EndUpdate; end; var I: Integer; begin ListBox1.LockDrawing; try for I := 1 to 10000 do ListBox1.Items.Add('Line ' + I.ToString); finally ListBox1.UnlockDrawing; end; |
In beiden Fällen ist die Performance deutlich höher (und sichtbar spürbar) als ohne eine der beiden Lösungen. Ein weiteres Szenario ist das einer Reihe von Änderungen an einer Komponente, die ein Repaint verursachen. Dies ist in einem einfachen Beispiel nicht trivial zu simulieren, aber eine Möglichkeit, mit Code wie diesem „absichtlich“ ein Flimmern zu verursachen:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
var I: Integer; begin Panel1.LockDrawing; try for I := 1 to 10000 do begin Panel1.Color := clBlue; Panel1.Repaint; Panel1.Color := clRed; Panel1.Repaint; end; finally Panel1.UnlockDrawing; end; |
Ich weiß, das ist ziemlich dumm, aber Sie können sehen, dass es bei den Lock/Unlock-Aufrufen kein Flimmern gibt, während der Effekt ziemlich schrecklich aussieht, ohne die Benutzeroberfläche zu sperren. Nicht, dass ich das einfach in einem Screenshot darstellen könnte, aber hier ist das Formular trotzdem zur Laufzeit:
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition