L’une des fonctionnalités ajoutées à la bibliothèque VCL dans Delphi 11 est la possibilité de gérer facilement le message Windows WM_SETREDRAW avec deux méthodes spécifiques ajoutées à la classe TWinControl : LockDrawing et UnlockDrawing
Je parcourais ma liste de choses à faire plus tôt cette semaine et j’ai trouvé un pas qui indiquait que je devais suivre le billet de blog que j’avais fait sur les nouvelles fonctionnalités VCL dans Delphi et C++Builder 11 à propos de LockDrawing. En fait j’ai écrit : « La classe TWinControl de base propose désormais les méthodes LockDrawing et UnlockDrawing, pour désactiver et contrôler la mise à jour. Cela déclenche l’exécution du message Windows WM_SETREDRAW. Cela vaut probablement son propre article de blog… ” mais j’ai totalement oublié cela. Voici donc le billet du blog, avec quelques mois de retard.
Commençons par l’API Windows. Le message WM_SETREDRAW est envoyé à une fenêtre pour « autoriser les modifications dans cette fenêtre à être redessinées, ou pour empêcher les modifications dans cette fenêtre d’être redessinées. » Chaque fois que vous devez effectuer un ensemble d’opérations, chacune nécessitant de repeindre, vous pouvez les mettre en attente et ne repeindre qu’à la fin, en évitant le scintillement et en accélérant le processus. Il est bien sûr important de supprimer le verrou et d’appeler une fonction spéciale pour forcer le repaint (RedrawWindow).
Tout cela est correctement encapsulé dans deux méthodes TWinControl ajoutées à la bibliothèque VCL dans RAD Studio 11, LockDrawing et UnlockDrawing, qui envoient le message WM_SETREDRAW avec les paramètres appropriés. Ils implémentent également une « logique de comptage de verrouillage » de sorte que si vous verrouillez deux fois le même contrôle, vous devez le déverrouiller deux fois pour reprendre la peinture. De plus, UnlockDrawing appelle automatiquement l’API RedrawWindow.
Cela dit, quels sont les cas d’utilisation ? J’ai écrit une démo montrant deux scénarios, et vous pouvez également consulter ce joli billet de blog de Radek Cervinka.
Un premier cas dans ma démo consiste à ajouter un tas d’éléments à une zone de liste. Alors que Delphi offrait traditionnellement et a toujours la possibilité d’éviter de repeindre en « gelant » la mise à jour de la liste de chaînes, il est logique de verrouiller la repeinture de l’interface utilisateur à la place. Voici les deux styles de codage alternatifs :
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; |
Dans les deux cas, les performances sont bien supérieures (et visibles perceptibles) que sans l’une des deux solutions. Un autre scénario est celui d’un ensemble de modifications apportées à un composant provoquant un repaint. Ce n’est pas trivial à simuler dans un exemple simple, mais une façon de provoquer un scintillement « exprès » avec un code comme celui-ci :
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; |
Je sais, c’est assez stupide, mais vous pouvez voir qu’il n’y a pas de scintillement avec les appels de verrouillage/déverrouillage, alors que l’effet semble assez horrible sans verrouiller l’interface utilisateur. Non pas que je puisse facilement rendre cela dans une capture d’écran, mais voici quand même le formulaire à l’exécution :
Design. Code. Compile. Deploy.
Start Free Trial Upgrade Today
Free Delphi Community Edition Free C++Builder Community Edition