2009-11-11 5 views
5

Normalement, lorsque je remplace la méthode OnPaint, je crée des plumes et des pinceaux, etc. à l'intérieur, puis je les dispose.Meilleure pratique pour la peinture de contrôle personnalisé dans Winforms?

J'ai aussi lu quelque part que, au lieu de recréer ces stylos et pinceaux, etc pour les créer, une fois en tant que membres statiques, puis les disposer une fois lorsque le formulaire est fermé, etc.

Est-ce une meilleure pratique?

Y a-t-il un meilleur moyen pour cela?

Je peux supposer que depuis OnPaint est appelé 1000s (?) De fois, cela créerait beaucoup de travail pour le GC par rapport à leur création qu'une seule fois.

Répondre

6

Si les pinceaux et les stylos ne changent pas, il est certainement préférable de les créer une fois et de les réutiliser. Notez, cependant, que si votre contrôle peut être utilisé sur plusieurs threads (ce qui est très improbable), vous devez les faire ThreadStatic (et initialiser lors de la première utilisation par thread) ou en faire des membres d'instance (et les disposer dans le contrôle Dispose de votre contrôle) Sinon, vous obtiendrez des erreurs GDI + non reproductibles, car les objets GDI + ne peuvent pas être utilisés sur plusieurs threads à la fois. La même chose est vraie pour les images. Si elles changent (par exemple, si vous utilisez des pinceaux de dégradé qui dépendent de la taille du contrôle), vous pouvez toujours les stocker dans des champs d'instance et les recréer lorsque la taille du contrôle (ou autre) change.

note, par ailleurs, que si vous utilisez des couleurs normales, vous pouvez utiliser les classes Brushes et Pens statiques, qui contiennent des brosses statiques et des stylos pour tous de .Net couleurs intégré et SystemBrushes et SystemPens pour les couleurs du système .

+0

Merci, encore une question: quand et comment vous appeler la méthode Dispose du contrôle? Je ne l'ai jamais appelé sur le contrôle avant. –

+1

Vous n'avez pas besoin de l'appeler; .Net l'appellera lorsque le contrôle parent est éliminé (lorsque vous disposez du formulaire sur lequel il se trouve). Si c'est sur votre formulaire principal, il sera disposé à la fin de l'appel 'Application.Run'. – SLaks

+0

Merci Slaks. Encore une chose :) Puisque je n'utilise généralement qu'un seul formulaire, si je crée un autre formulaire qui n'est pas un formulaire principal, je dois le jeter après qu'il soit fermé? –

1

Ce que je ferais, ce serait de faire des pinceaux et des stylos en tant que membres du contrôle personnalisé, puis de les disposer lors de la mise au rebut du contrôle. De cette façon, vous réutilisez le même pinceau/stylo chaque fois qu'OnPaint est appelé. Cependant, je ne les déclarerais pas comme static, car vous ne seriez pas en mesure de savoir quand vous pouvez vous débarrasser de vos objets. Mais comme SLaks l'a mentionné, s'il y a beaucoup d'instances du contrôle en mémoire en même temps, il peut être judicieux de créer des pinceaux et des stylos comme statiques afin de n'avoir qu'une seule instance de chaque objet créé pour la durée de vie de votre application .

+0

S'il y aura beaucoup d'instances du contrôle, ce serait une très bonne idée de les rendre statiques. Il n'y a rien de mal à avoir quelques brosses qui traînent. – SLaks

+1

C'est un bon point, s'il y a beaucoup d'instances de ce contrôle, rendre les pinceaux et les stylos statiques serait une bonne idée. –

0

Une meilleure pratique consiste à utiliser des stylets système et des pinceaux, car ceux-ci sont optimisés pour une consommation de ressources minimale.

+0

Seulement s'il utilise des couleurs intégrées statiques. – SLaks

2

J'ai lu un interesting article le mois dernier qui vous suggérait de faire toute votre peinture sur un objet BufferedGraphics séparé, et de faire que la méthode on_paint fasse une copie directe de celle-ci vers l'objet graphique de votre contrôle. De cette façon, la peinture est plus rapide et vous ne mettez à jour votre BufferedGraphics que lorsque quelque chose de significatif change (par exemple, une ligne se déplace ou le texte change).

+1

Uhm, pas si excelent. Il suppose certaines mauvaises choses comme dessiner le contrôle complet au lieu du rectangle coupé. La plupart du temps ce ne sera pas le plus rapide. En outre, il crée manuellement un double tampon au lieu d'utiliser le ControlStyles.DoubleBuffer fourni par le système, apparemment sans raison. Il peut être utile de retirer le code de votre gestionnaire OnPaint, mais cet article a plus de fonctionnalités "bonus" qui ne sont pas très bonnes. –

1

Je dépend vraiment de ce que vous peignez. Si vous peignez quelque chose qui n'est repeint qu'à la suite d'une interaction de l'utilisateur, vous pouvez perdre vos soucis de performance et créer tous les objets graphiques ad-hoc si nécessaire.

Assurez-vous que vous avez Dispose() tout ce dont vous avez besoin dans vos graphiques. Stylos, pinceaux, régions, polices. Ce sont tous des objets GDI et sont liés au système par des poignées GDI.

Si vous avez besoin de graphiques animés d'une manière ou d'une autre ou que vous les modifiez dans le temps sans que l'utilisateur ne clique dessus, préparez tous vos objets graphiques devant et réutilisez-les autant que possible. La règle qui peut être appliquée ici est qu'il vaut mieux perdre la mémoire que des millisecondes en dessinant chaque image de l'animation. Enfin, au moins pour ce post, n'oubliez pas d'utiliser le double-buffer, soit automatique dans le système de contrôle .net ou roll-your-back-bitmap style.

Amusez-vous GDI-ing :)

Questions connexes