Double Buffering [Résolu]

Signaler
Messages postés
903
Date d'inscription
mercredi 23 février 2005
Statut
Membre
Dernière intervention
16 juin 2010
-
Messages postés
903
Date d'inscription
mercredi 23 février 2005
Statut
Membre
Dernière intervention
16 juin 2010
-
Bonjour à tous,



En faite j'ai un panel avec un fond blanc et je voudrais faire bouger
un carré noir dessus avec les touches sans que ca scinitlle avec la
méthode :



public void EnableDoubleBuffering()
{
// Set the value of the double-buffering style bits to true.
this.SetStyle(ControlStyles.DoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint,
true);
this.UpdateStyles();
}

Je me suis servis de cette fonction pour mon panel mais là j'ai pas trop compris, parceque soit le fond
blanc reste mais le carré noir à tendance a laisser une trainée derriere lui ou soit le fond blanc reste
et le carré noir à tendance à disparaitre quand je relache une touche.

Si quelqun avait une idée...

Par avance, merci.

17 réponses

Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Modérateur
Dernière intervention
14 février 2014
36
alors... la solution la plus simple est la suivante :



fait un override de la méthode OnPaint comme ceci :



protected override void OnPaint(PaintEventArgs e) {

//base.OnPaint (e);

Bitmap bitmap = new Bitmap(this.Width, this.Height);



Graphics g = Graphics.FromImage(bitmap);

// tu dessines dans ton objet Graphics g

// ...

// et, à la fin

e.Graphics.DrawImage(bitmap,0,0);

g.Dispose();

bitmap.Dispose();

}



Séb

<hr>Sébastien FERRAND

Blog : http://blogs.developpeur.org/sebmafate
Messages postés
108
Date d'inscription
vendredi 11 juillet 2003
Statut
Membre
Dernière intervention
27 novembre 2007

1) Il faut simplement utiliser une variable membre pour conserver la position actuelle du rectangle.
2) Effectuer un offset de ce rectangle suivi d'un Invalidate() suite à l'utilisation des touches de déplacement.
3) Surcharger OnPaint() pour y remplir ce rectangle à l'aide de la méthode e.Graphics.FillRectangle(...)

-- AOGie --
Messages postés
3246
Date d'inscription
lundi 25 avril 2005
Statut
Modérateur
Dernière intervention
27 octobre 2012
38
Sebmafate, pourquoi tu preferes qu'il utilise son propre double buffer plutot que le double buffering "automatique", y'a une raison particulière ( à part éviter d'appeler Invalidate ) !?

Emmanuel9, Oui avec la methode de Sebmafate tu n'es plus oblige d'utiliser Invalidate donc plus besoin de OnPaint, tu utilises à la place Control.CreateGraphics( ) et tu le dispose à la fin.

private void Draw( )
{
using ( Graphics g = this.CreateGraphics( ) )
{
// ...
}
}


Sinon chez moi ca marche avec SetStyle:

class MyPanel : Panel
{
private int x;
private int y;


public MyPanel( ) : base( )
{
this.SetStyle( ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint | ControlStyles.DoubleBuffer, true );
}


// OnPaint

protected override void OnPaint( PaintEventArgs args )
{
//base.OnPaint( args );

Graphics g = args.Graphics;

g.Clear( SystemColors.Window );
g.FillRectangle( SystemBrushes.WindowText, x, y, 100, 100 );
}


// OnMouseMove


protected override void OnMouseMove( MouseEventArgs args )
{
//base.OnMouseMove( args );


x = args.X;
y = args.Y;


Invalidate( );
}
}
Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Modérateur
Dernière intervention
14 février 2014
36
pourquoi utiliser cette méthode, plutot qu'en automatique...



et bah, en fait, c'est plus rapide... surtout pour de gros graphiques...

mes sources :

Mitsu Furuta aux rencontres Windows Forms,

Frédéric Mélantois : http://www.dotnet-tech.com, article Double Buffering


<hr>Sébastien FERRAND

Blog : http://blogs.developpeur.org/sebmafate
Messages postés
3246
Date d'inscription
lundi 25 avril 2005
Statut
Modérateur
Dernière intervention
27 octobre 2012
38
En fait Windows appele OnPaint quand ta forme à besoin d'être redessinée, par exemple si une autre fenêtre est passée dessus.. c'est ca le principe du message WM_PAINT en interne.. Mais si tu dessines à intervalles reguliers et rapides sur ta forme, par exemple à 60 frames par secondes ( fps ) et bien là on s'en "tape" du message WM_PAINT car ta forme en sans cesse redessinée.. Pour ca tu implementes un timer qui appele une methode Draw comme celle que j'ai ecrite plus haut ou alors une boucle principale avec DoEvent.. Normalement une application "bureautique" n'a pas besoin de ce genre de technique..
Messages postés
903
Date d'inscription
mercredi 23 février 2005
Statut
Membre
Dernière intervention
16 juin 2010
2
merci de te réponse, et une petite question est t'on tjs obligé de dessiner dans onpaint ?
Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Modérateur
Dernière intervention
14 février 2014
36
oui l'utilisation du OnPaint est... obligatoire... sinon si tu passes
un "objet" au dessus de ta fenêtre, tu perdras le dessin de ton
rectangle.

<hr>Sébastien FERRAND

Blog : http://blogs.developpeur.org/sebmafate
Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Modérateur
Dernière intervention
14 février 2014
36
aogie ---> ta méthode fonctionne... mais est moins "générale".



elle ne fonctionne que s'il n'existe qu'un seul objet à dessiner.

<hr>Sébastien FERRAND

Blog : http://blogs.developpeur.org/sebmafate
Messages postés
3246
Date d'inscription
lundi 25 avril 2005
Statut
Modérateur
Dernière intervention
27 octobre 2012
38
Mince j'ai été trop long, ma question arrive après vos réponses :(
Messages postés
3246
Date d'inscription
lundi 25 avril 2005
Statut
Modérateur
Dernière intervention
27 octobre 2012
38
Hum, vous n'allez pas comprendre ma methode Draw, si je ne precise pas que je dessine plusieurs FPS avec un timer, donc je me fou du message WM_PAINT !
Messages postés
3246
Date d'inscription
lundi 25 avril 2005
Statut
Modérateur
Dernière intervention
27 octobre 2012
38
Ah ok.. C'est bon a savoir.. J'avais pas remarqué que c'etait plus rapide, mais il faut dire que j'utilise aussi mon propre buffer quand j'ai de nombreuses operations graphiques.. Avec la même technique, mais je crée le bitmap et son graphics associé dans la fonction OnResize pour qu'il est toujours la bonne taille et surtout gagner en performance, ca evite de créer ces deux objets plusieurs fois par secondes, dans le cas d'un jeu par exemple..
Messages postés
903
Date d'inscription
mercredi 23 février 2005
Statut
Membre
Dernière intervention
16 juin 2010
2
Moi j'avais fais ca en faite ca marche mais vos réponses on l'air plus interessantes, qu'en pensez vous ?




public void EnableDoubleBuffering()
{
// Set the value of the double-buffering style bits to true.
this.SetStyle(ControlStyles.DoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint,
true);
this.UpdateStyles();
}


dans l'événement : load :



i = 0 ; // variable global

EnableDoubleBuffering() ;



dans l'événement : mouse_move :



i++ ;

panel1.Invalidate() ;



dans l'évenement : paint :



SolidBrush br1 = new SolidBrush(Color.Black) ;

e.Graphics.Clear(Color.White) ;

e.Graphics.FillRectangle(br1,20,20+i,40,40) ;



et si mettons dans paint j'appelle cette fonction avec e.get_Graphics() en paramètre ?



ma_fonction_de_dessin(Graphics e)

{

// la je dessine

}
Messages postés
903
Date d'inscription
mercredi 23 février 2005
Statut
Membre
Dernière intervention
16 juin 2010
2
la fonction EnableDoubleBuffering(), c'est ca plutôt :

public void EnableDoubleBuffering()
{
// Set the value of the double-buffering style bits to true.
panel1.SetStyle(ControlStyles.DoubleBuffer |
ControlStyles.UserPaint |
ControlStyles.AllPaintingInWmPaint,
true);
panel1.UpdateStyles();
}
Messages postés
4936
Date d'inscription
lundi 17 février 2003
Statut
Modérateur
Dernière intervention
14 février 2014
36
oui ca marche aussi...

mais, c'est bête, mais pourquoi utilises-tu e.get_Graphics() alors qu'il existe e.Graphics ?

<hr>Sébastien FERRAND

Blog : http://blogs.developpeur.org/sebmafate
Messages postés
903
Date d'inscription
mercredi 23 février 2005
Statut
Membre
Dernière intervention
16 juin 2010
2
Disons q'en faite à terme j'aurais voulu dessiner un graphique en camembert avec une fonction



Camembert(ArrayList * statistique)



J'ai un treeview avec des personnes, je cliques sur une personne, je
calcule les statistiques de cette personne, je recupere une arrayList
de statistiques et j'appelle ma fonction Camembert. Ca marche mais dès
qu'on sort de l'ecran ca disparait enfin y'a plus de truc qui vont pas.
Messages postés
903
Date d'inscription
mercredi 23 février 2005
Statut
Membre
Dernière intervention
16 juin 2010
2
Ben je sais pas en faite, la seule manière pour que ce l'on dessine, ne
disparaissent pas quand la form sort de l'ecran c'est de dessiner dans
l'event paint ?
Messages postés
903
Date d'inscription
mercredi 23 février 2005
Statut
Membre
Dernière intervention
16 juin 2010
2
ok , merci.