J'ai deux problèmes avec un contrôle utilisateur propre qui utilise des bitmaps :
- Il clignote s'il est redessiné par la méthode "Refresh" de .NET.
- Il a une mauvaise performance.
Le contrôle se compose de trois bitmaps :
- Une image de fond statique.
- Un rotor en rotation.
- Une autre image en fonction de l'angle du rotor.
Tous les bitmaps utilisés ont une résolution de 500x500 pixels. Le contrôle fonctionne comme suit : https://www.dropbox.com/s/t92gucestwdkx8z/StatorAndRotor.gif (c'est une animation gif)
Le contrôle utilisateur doit se dessiner à chaque fois qu'il reçoit un nouvel angle de rotor. Par conséquent, il possède une propriété publique 'RotorAngle' qui ressemble à ceci :
public double RotorAngle
{
get { return mRotorAngle; }
set
{
mRotorAngle = value;
Refresh();
}
}
Refresh
soulève le Paint
événement. Le site OnPaint
Le gestionnaire d'événement ressemble à ceci :
private void StatorAndRotor2_Paint(object sender, PaintEventArgs e)
{
// Draw the three bitmaps using a rotation matrix to rotate the rotor bitmap.
Draw((float)mRotorAngle);
}
Mais lorsque j'utilise ce code - qui fonctionne bien dans d'autres contrôles utilisateur - le contrôle utilisateur n'est pas affiché du tout si le contrôle est mis en double tampon via SetStyle(ControlStyles.OptimizedDoubleBuffer, true)
. Si je ne mets pas cet indicateur à true, le contrôle clignote lorsqu'il est redessiné.
Dans le constructeur de contrôle, je mets :
SetStyle(ControlStyles.AllPaintingInWmPaint, true);
SetStyle(ControlStyles.ContainerControl, false);
// User control is not drawn if "OptimizedDoubleBuffer" is true.
// SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.SupportsTransparentBackColor, true);
Tout d'abord, je pensais que le clignotement était dû au fait que l'arrière-plan est effacé chaque fois que le contrôle est dessiné. Par conséquent, j'ai défini SetStyle(ControlStyles.AllPaintingInWmPaint, true)
. Mais ça n'a pas aidé.
Alors, pourquoi ça clignote ? Les autres contrôles fonctionnent très bien avec cette configuration. Et pourquoi le contrôle n'est-il pas affiché si SetStyle(ControlStyles.OptimizedDoubleBuffer, true)
.
J'ai découvert que le contrôle ne clignote pas si j'invoque ma méthode de contrôle de la qualité de l'air. Draw
directement après avoir modifié la propriété RotorAngle
:
public float RotorAngle
{
get { return mRotorAngle; }
set
{
mRotorAngle = value;
Draw(mRotorAngle);
}
}
Mais cela se traduit par de très mauvaises performances, notamment en mode plein écran. Il n'est pas possible de mettre à jour le contrôle toutes les 20 millisecondes. Vous pouvez l'essayer vous-même. Je joins ci-dessous la solution complète de Visual Studio 2008.
Alors, pourquoi cette performance est-elle si mauvaise ? Ce n'est pas un problème de mettre à jour d'autres (propres) contrôles toutes les 20 millisecondes. Est-ce vraiment dû aux bitmaps ?
J'ai créé une solution visuelle simple de Visual Studio 2008 pour démontrer les deux problèmes : https://www.dropbox.com/s/mckmgysjxm0o9e0/WinFormsControlsTest.zip (289,3 KB)
Il y a un exécutable dans le répertoire bin\Debug
.
Merci pour votre aide.