atomefougere
Messages postés32Date d'inscriptionmercredi 1 septembre 2004StatutMembreDernière intervention 5 décembre 2005
-
29 oct. 2005 à 00:33
ikaemos
Messages postés9Date d'inscriptionlundi 6 septembre 2004StatutMembreDernière intervention 4 décembre 2005
-
5 déc. 2005 à 21:31
Salut tout le monde.
Je vous explique mon problème :
J'ai codé un composant qui hérite de la ListBox. Je gère le redimensionnement de ses items en fonction du texte qui doit y être affiché. J'ai notamment surchargé la méthode OnDrawItem pour dessiner mes items.
J'ai un clignotement assez désagréable, que j'ai essayé de supprimer en utilisant le double buffering sur mon composant. Dans le constructeur, j'ajoute donc les instructions :
- Lorsque je n'apelle pas les SetStyle, mes items se dessinent bien, mais ça clignote
- Lorsque j'apelle les SetStyle, mes items ne se dessinent plus. Il semblerait que ce soit le :
SetStyle(System.Windows.Forms.ControlStyles.UserPaint, true);
qui empêche le dessin. Si je le commente, le dessin de fait bien, mais ça clignote toujours.
sebmafate
Messages postés4936Date d'inscriptionlundi 17 février 2003StatutMembreDernière intervention14 février 201437 31 oct. 2005 à 12:34
après moultes recherches... je suis arrivé à la conclusion qu'étant donné que le contrôle standard à le même conmportement (clignotement lors du redimensionnement), à moins de refaire ton propre controle... je crains que tu n'arriveras pas à tes fins
cs_badrbadr
Messages postés475Date d'inscriptionjeudi 19 juin 2003StatutMembreDernière intervention 3 novembre 20081 31 oct. 2005 à 16:12
ca tourne au drame avec ce mechant ListBox ici
Je vais donc dire ce que je connais du double buffering en espérant que ça donne des idées
le fait d'activer le double buffering avec SetStyle(ControlStyles.DoubleBuffer, true) ne résout que la moitié du problème.
Windows dessines un contrôle ou une fenetre en trois étapes. D'abord il efface la région en dessinant avec une couleur à lui. Deuxièmement, il envoie l'événement PaintBackground à la fenêtre ou au contrôle pour dessiner l'arrière plan (chose que la classe d'orginie fait generalement pour nous en utilisant BackColor ou BackgroundImage) et la troisième phase est le dessin final avec Paint.
le Double Buffering fusionne l'étape deux et l'étape trois. pour corriger l'étape un, il faut utiliser le falg AllPaintingInWmPaint
Bon jusqu'à date, vous savez ca...
mais qu'est ce que vous pensez d'override la methode OnPaintBackground()
ca sera interressant d'essayer ca:
protected override void OnPaintBackground(PaintEventArgs e)
{
//ne pas utiliser la méthode de la classe base
//base.OnPaintBackground(e)
e.Graphics.FillRectangle(Brushes.Black, this.ClientRectangle);
}
voila.....
j'espère que ca va aider, j'aime pas ca avancer des théories sans les expérimenter mais c'est que j'ai pas le temps
Ah oui, j'ai eu l'air intelligent dans ce poste là, fe que il importe que je donne mes source
Windows Forms Programming in C# by Chris Sells page 210
atomefougere
Messages postés32Date d'inscriptionmercredi 1 septembre 2004StatutMembreDernière intervention 5 décembre 2005 31 oct. 2005 à 16:26
Merci pour l'intérêt que vous portez tous à la question, vraiment.
Cependant badrbadr, je ne pense pas que le fait de surcharger le PainBackground change quelque chose... J'ai bien compris le principe du double buffering, mais le problème ici, c'est qu'on ne peut l'activer que si on dessine le composant dans le OnPaint.
Or il est plus intuitif et plus pertinent à mon avis de gérer le dessin d'une listBox item par item, en surchargeant le OnDrawItem. Seulement, le fait de travailler avec le OnDrawItem n'est pas compatible avec le OnPaint... Le OnPaint de la classe de base est censé dessiner les items et déclancher les évenements OnDrawItem, mais pour une raison inconnue, à partir du moment ou on surcharge le OnDrawItem dans la classe fille, le contrôle ne supporte plus le double buffering. Lorsque je dessine tout dans le OnPaint, le doubleBuffer est actif, mais ca devient ingérable avec le scrolling.
Enfin j'sais plus trop quoi penser, ça m'embête vraiment, et je suis déçu de constater ça alors que dans d'autres langages, utilisant aussi gdi, tout se passe bien...
(enfin tout dépend si tu as besoin de resizeRedraw, mais le Opaque permet d'éviter de tracer le fond, et donc évite de substituer le OnPaintBackground pour le court circuiter)
ensuite il suffit de substituer OnMouseMove et OnMouseLeave pour invalider que les lignes nécessaires (la précedente et celle en cours). On définira l'élément "myOverIndex" comme étant l'élément en mouseover de la listbox (très utile si on veut vraiment repeindre TOUTE la ligne sans utiliser le DrawBackground) :
/// <summary>
/// Index de l'élément en mode "Over".
/// </summary>
private
int myOverIndex = -1;
Tout ça évite de redessiner si il n'y a pas besoin, et d'invalider l'intégralité du contrôle. Ca n'enlève pas l'effet de scintillement mais le rend quasiement imperceptible ;)
Voili, j'espère que ça correspond à tes attentes :)
Vous n’avez pas trouvé la réponse que vous recherchez ?
ikaemos
Messages postés9Date d'inscriptionlundi 6 septembre 2004StatutMembreDernière intervention 4 décembre 2005 4 déc. 2005 à 00:31
Ah vi juste une chose : il faut éviter d'utiliser un SmoothingMode spécial pour tracer les contours d'une ligne, sinon ça colle des cocheneries sur les bords des lignes (à cause du mode opaque qui empeche le tracé du fond). L'idéal si tu veux utiliser un SmoothingMode spécial est de ne l'utiliser que pour tracer des éléments et de le remettre en mode par défaut ensuite.