soussous78
Messages postés47Date d'inscriptionmardi 21 novembre 2006StatutMembreDernière intervention 5 novembre 2016
-
17 janv. 2013 à 12:59
vikingch
Messages postés7Date d'inscriptionjeudi 30 janvier 2014StatutMembreDernière intervention20 mars 2014
-
4 févr. 2014 à 10:39
Bonjour,
J'ai un petit soucis avec une classe que j'ai fait.
Cette (exactement ces) classe, permet d'afficher un bandeau avec un message qui défile. Or ce message me fait des freeze. Quelqu'un aurait une idée d'où cela pourrait venir, ou une meilleure idée pour ce faire?
tout d'abord j'ai une classe de thread pour créer l'image :
public class T_Texte
{
public event BMPEventHandler OnBitmapCreated;
string texte;
Color BackColor;
Color ForeColor;
Control Parent;
Font f;
public T_Texte(string texte, Color BackColor, Color ForeColor, Control Parent, Font f)
{
this.texte = texte;
this.BackColor = BackColor;
this.ForeColor = ForeColor;
this.Parent = Parent;
this.f = f;
}
public void Run()
{
#region calcul de la taille du texte
Bitmap bmp = new Bitmap(10, 10);
Graphics g = Graphics.FromImage(bmp);
//on entre la taille du texte dans un SizeF
SizeF S_texte= g.MeasureString(texte, f);
g.Dispose();
double longeurTotale = S_texte.Width + Parent.Width;//longeur du texte+ecran
double nbPixSec = (double)Parent.Width/10;//nombre de pixel par seconde (10 seconde pour traverser l'ecran)
int nbSec = 1+(int)(longeurTotale / nbPixSec);//nombre de seconde nécessaire pour traverser l'écran avec sa propre longeur
#endregion
DateTime dt_fin = DateTime.Now.AddSeconds(nbSec); //heure de la fin de défilement
DateTime dt_now = DateTime.Now;//heure actuelle
while (Statique.ProgramRun && dt_fin > dt_now) //Statique.ProgramRun est la porte de sortie du thread si on éteint le programme
{
// création du bitmap de sortie
Bitmap b = new Bitmap(Parent.Width,Parent.Height);
Graphics gr = Graphics.FromImage(b);
//recherche du centre du panel
float Top = Parent.Height / 2 - S_texte.Height / 2;
//on calcule l'emplacement gauche de l'ecriture
double milisecRest=(dt_fin-dt_now).TotalMilliseconds;
double nbpix=milisecRest*nbPixSec/1000;
float Left = (float)nbpix - S_texte.Width;
// on dessine le fond et l'ecriture
gr.FillRectangle(new SolidBrush(BackColor), new Rectangle(0, 0, Parent.Width, Parent.Height));
gr.DrawString(texte, f, new SolidBrush(ForeColor), Left, Top);
//
gr.Dispose();
OnBitmapCreated(this,new ImgClassEventArgs(b));
//on réalloue dt_now
dt_now = DateTime.Now;
}
}
}
J'ai ensuite un control ou sera déssiné le bandeau:
public partial class Texte : UserControl
{
Bitmap bmp;
public Texte()
{
InitializeComponent();
//double buffer
this.DoubleBuffered = true;
this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint | ControlStyles.OptimizedDoubleBuffer, true);
UpdateStyles();
}
/// <summary>
/// classe qui démarrera te thread
/// </summary>
public void run(string texte, Color BackColor, Color ForeColor, Font f)
{
T_Texte tt = new T_Texte(texte, BackColor, ForeColor, this, f);
tt.OnBitmapCreated += new BMPEventHandler(ti_OnBitmapCreated);
Thread t = new Thread(new ThreadStart(tt.Run));
t.Start();
}
void ti_OnBitmapCreated(object sender, ImgClassEventArgs e)
{
bmp = e.bmp;
this.Invalidate();
}
protected override void OnPaint(PaintEventArgs e)
{
if (bmp != null)
e.Graphics.DrawImage(bmp, e.ClipRectangle);
}
}
yann_lo_san
Messages postés1137Date d'inscriptionlundi 17 novembre 2003StatutMembreDernière intervention23 janvier 201626 17 janv. 2013 à 13:48
Salut,
c'est pas plutôt sur le formulaire parent qu'on devrait activer le Dbl Buffer ?
Sinon, beaucoup d'allocation dans la boucle du Thread (while), Bitmap, Graphics ect...
Ne pourrais tu pas référencer des membres de la classe une seule fois ??!!
et faire le Dispose lors de l'arret du thread.
1 seul new Bitmap
1 seul CreateGraphics
les 2 float et les 2 doubles déclarés hors de la pile aussi
1 seul ImgClassEventArgs en rajoutant un setter bitmap à la place d'appeler le constructeur
soussous78
Messages postés47Date d'inscriptionmardi 21 novembre 2006StatutMembreDernière intervention 5 novembre 2016 17 janv. 2013 à 15:31
Merci d'avoir regardé,
- J'avais essayé avec un seul bitmap mais j'avais un soucis de clignotement.
Je pense a cause du fait que le bitmap était construit dans un thread et que le onpaint est dans un autre, et le fait de ne pas recréer l'image, le onpaint doit parfois dessiner lorsque je met la couleur du fond.
- Les float et double sont dans la boucle car le formulaire initial peut être agrandit.
- pour le ImgClassEventArgs, je ne vois pas ce qu'est un setter Bmp.
Pour le Buffer, il est bien a la bonne place, c'est moi qui ai mal choisi mon nom de variable. Je ne dessine pas sur le parent mais bien sur le controle..
soussous78
Messages postés47Date d'inscriptionmardi 21 novembre 2006StatutMembreDernière intervention 5 novembre 2016 12 févr. 2013 à 21:21
Bonjour,
J'ai tenté d'une autre manière :
J'ai fait appeler entrer le control dans le constructeur et tente d'afficher directement dans le control a partir du thread.
Du coup je crée un bitmap au début du thread (imgGardee ) et un graphics pour dessiner dedans.
Dès le début, je crée le graphics correspondant au control.
Et au moment de l'affichage, je colle l'imgGardee dabs le graphics du control.
Donc le GC ne s'occupe ni des bitmap ni des graphics.
Mon problème de saccade est toujours d'actualité. Je suis vraiment a cours d'idée. Si un oeil neuf me trouve où le code pêche ou si quelqu'un trouve un code permettant de faire défiler un texte dans un bandeau sans saccade. Je suis preneur.
public void Run()
{
Bitmap imgGardee = new Bitmap(s.Width, s.Height);
Graphics gr = Graphics.FromImage(imgGardee);
Graphics grSend = c.CreateGraphics();
double nbpixelSec = s.Width / 10;
double TotalWidth = s.Width + gr.MeasureString(texte, font).Width;
double duree = (TotalWidth)/nbpixelSec;
DateTime dtnow = DateTime.Now;
DateTime dtfin = DateTime.Now.AddSeconds(duree);
DateTime dtdebut = dtnow;
#region Boucle
while (dtfin > dtnow)
{
#region en cas de resize
if (s != c.Size)
{
s = c.Size;
imgGardee = new Bitmap(s.Width, s.Height);
gr = Graphics.FromImage(imgGardee);
grSend = c.CreateGraphics();
TotalWidth = s.Width + gr.MeasureString(texte, font).Width;
}
#endregion
double ratio = (dtfin-dtnow).TotalMilliseconds/(dtfin - dtdebut).TotalMilliseconds;
double left = TotalWidth * ratio - (int)gr.MeasureString(texte, font).Width;
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
gr.FillRectangle(new SolidBrush(Color.Black),new Rectangle(new Point(0,0),s));
gr.DrawString(texte, font, new SolidBrush(Color.White), new Rectangle((int)left, 0, 1+(int)gr.MeasureString(texte,font).Width, (int)s.Height), sf);
grSend.DrawImage(imgGardee, new Rectangle(0, 0, s.Width, s.Height));
dtnow = DateTime.Now;
Thread.Sleep(10);
}
gr.Dispose();
grSend.Dispose();
gr.Dispose();
c.Fini = true;
#endregion
}
vikingch
Messages postés7Date d'inscriptionjeudi 30 janvier 2014StatutMembreDernière intervention20 mars 2014 4 févr. 2014 à 10:39