[C#/Winform] Scrolling

Pour une application sur laquelle je bosse, je suis censé faire défiler du texte. Pas énormément, puisqu’il ne s’agit que d’une ligne de texte qui scroll de manière horizontale. L’appli en question est faite en C#. J’ai regardé un peu partout sur le net (notamment sur codeproject) et j’ai rien trouvé qui me retourne en terme de qualité finale (il ne faut pas que ca soit saccadé, ni que pour cela ca bouffe 108% des ressources du processeur). Du coup je me demandait si quelqu’un ici avait déjà trouvé une solution satisfaisante. Je suis ouvert à toutes les possibilités (j’ai même exploré le browser embed avec scrolling en flash ou en JS). Dernier point important, certains élements qui scrollent doivent être cliquables.

Vous avez deux heures B)

ok, il reste 1h40, et je te propose ma methode brute.

Surcharges un Control, surcharges la methode OnPaint & OnClik, et voilou. Rien de bien sorcier. (Apres, la methode doit etre loin d’etre ideale, mais je le sens bien comme ca).

[quote=“AnA-l, post:2, topic: 33785”]ok, il reste 1h40, et je te propose ma methode brute.

Surcharges un Control, surcharges la methode OnPaint & OnClik, et voilou. Rien de bien sorcier. (Apres, la methode doit etre loin d’etre ideale, mais je le sens bien comme ca).[/quote]

vip, GDI+ est l’ami de tout le monde pour ca, le seul soucis c’est qu’on est pas vraiment en phase avec le degré de qualité que j’espère obtenir B)

Comment ca ?

Ben sur les exemples que j’ai pu trouver sur le net, en terme de fluidité et d’absence de saccades, c’est pas ca :confused:

Baon, t’as jetté un oeil la dessus ?

http://www.codeproject.com/cs/miscctrl/dou…ingtextctrl.asp et ca http://www.codeproject.com/cs/miscctrl/ScrollingAbout.asp

[quote=“AnA-l, post:6, topic: 33785”]Baon, t’as jetté un oeil la dessus ?

http://www.codeproject.com/cs/miscctrl/dou…ingtextctrl.asp et ca http://www.codeproject.com/cs/miscctrl/ScrollingAbout.asp[/quote]

Comme on disait sur IRC donc, c’est le concept que je cherche, mais pas fait cradement comme ces deux exemples. Je reste donc ouvert à tout retour d’expérience sur le sujet B)

Une solution qui n’utilise pas de Timer (si c’est ça que tu considères crade), je ne pense pas que ce soit possible.

Pour éviter le clignotement, je me contenterai du double buffering (y’a pas de secret). Avec un timer adéquat, je ne vois pas pourquoi ça boufferai trop de ressources. Le Invalidate() est très bien fait pour gérer les ressources processeur.

Tiens, voilà un sample fait en 5 minutes, dont le résultat me semble relativement correct.

J’invite les gourous à critiquer mes choix (je ne sais pas, notamment, si le Timer winform est le plus adapté, j’ai pas pris le temps de réfléchir à ça).

[codebox]
public class ScrollingLabel : Label
{
public ScrollingLabel()
{
SetStyle(ControlStyles.OptimizedDoubleBuffer, true);

    _timer = new Timer();
    _timer.Interval = TIMER_INTERVAL;
    _timer.Start();
    _timer.Tick += new EventHandler(Timer_Tick);
}

protected override void Dispose(bool disposing)
{
    base.Dispose(disposing);

    if (disposing)
    {
        if (_timer != null)
            _timer.Dispose();
    }
}

// Ajustable, détermine la période (ici 25 paint/seconde au maximum)
const int TIMER_INTERVAL = 40;

// Largeur du texte, mise en cache
int _textWidth;

Timer _timer;

// Décalage horizontal, MinValue pour une valeur non initialisée
int _offset = int.MinValue;

// Intervalle par défaut entre chaque incrément
int _scrollingIncrement = 3;

public int ScrollingIncrement
{
    get { return _scrollingIncrement; }
    set { _scrollingIncrement = value; }
}

public override string Text
{
    get { return base.Text; }
    set
    {
        if (Text != value)
        {
            base.Text = value;
            _textWidth = -1;
        }
    }
}

public override Font Font
{
    get { return base.Font; }
    set
    {
        if (base.Font != value)
        {
            base.Font = value;
            _textWidth = -1;
        }
    }
}

void Timer_Tick(object sender, EventArgs e)
{
    _offset += _scrollingIncrement;
    Invalidate();
}

protected override void OnPaint(PaintEventArgs pe)
{
    if (_textWidth == -1)
        _textWidth = (int)pe.Graphics.MeasureString(Text, Font).Width;

    Rectangle drawRectangle = DisplayRectangle;

    if (_scrollingIncrement > 0)
    {
        if (_offset > drawRectangle.Width || _offset == int.MinValue)
        {
            _offset = 0 - _textWidth;
        }
    }
    else
    {
        if (_offset < -_textWidth || _offset == int.MinValue)
        {
            _offset = drawRectangle.Width;
        }
    }
    drawRectangle.Offset(_offset, 0);
    TextRenderer.DrawText(pe.Graphics, Text, Font, drawRectangle, ForeColor, TextFormatFlags.Default | TextFormatFlags.VerticalCenter | TextFormatFlags.NoClipping);
}

}
[/codebox]

[quote=“Styx31, post:9, topic: 33785”]Tiens, voilà un sample fait en 5 minutes, dont le résultat me semble relativement correct.

J’invite les gourous à critiquer mes choix (je ne sais pas, notamment, si le Timer winform est le plus adapté, j’ai pas pris le temps de réfléchir à ça).[/quote]

Merci Styx d’y avoir consacré du temps. Ca me navre d’autant plus d’être critique après ca, mais ca scroll pas top. J’ai tenté en réduisant l’incrémentation, en réduisant la vitesse de scroll et tout, mais j’ai encore l’impression que ca scintille (j’ai même vérifié la fréquence de mon moniteur). En fait, il faudrais d’abord que je regarde si qque part un soft à un scroll qui me plait, histoire de savoir si ca existe tout court, ou si c’est juste moi qui suit trop exigeant (ce qui est fort possible d’ailleurs).

Quoi qu’il en soit, merci encore. Au pire, si je trouve pas mon bonheur, ta solution à le mérite d’être propre et efficace.

c0unt0, guru, dit a propos du style :
“C’est pas mal, mais je trouve que le choix de couleur pour la bande en haut de la section code n’est peut-etre pas le meilleur : il brise l’armonie du reste de la page”.

Voila, c’est c0unt0, guru et critique de style.

Truc tout bete, t’as le droit au Framework 3.0 ? Dans ce cas là, tu mets un WPFHost dans ton appli winform, un TextBlock avec une TextAnimation, et voilà… Tu as du texte vectoriel animé dans une surface de manière super fluide B)

A priori oui, le Framework 3.0 ne devrait pas poser de problème, tant que ca marche aussi sous XP. Je précise parce que je n’ai trouvé aucune des référence à ce dont tu me parle sur MSDN. Tu aurais un lien direct stp ?

Ben ca revient a hoster un truc pseudo equivalent a ce qui est dans ce xbapp (clique si t’as .net 3.0 installed xp ou vista):

http://xamlxaml.com/examples/ScrollingCanv…vasExample.xbap

mais dans un winforms au lieu de IE a l’aide d’un objet ElementHost qui vit dans WindowsFormsIntegration.

J’ai pas vu le code du XBap, mais ca m’a l’air assez mauvais… l’animation saccade vachement… Je regarderai ca, et sinon je te ferai un bout de code qui fait ca.

Ok, après examen du code, c’est clairement foireux. Le gars utilise pas de RenderTransform, mais modifie les coordonnées des contrôles, du coup c’est pas accéléré en hardware… Bon, bah je sais comment occuper ma première heure de l’aprem ^^.

Oui c’est pour ca que j’ai dit pseudo equivalent et que j’ai pas file le lien vers le source B) c’etait plus pour illustrer comment hoster et ce que c’etait que dire comment faire ou donner une idee du resultat final B) Desolé si j’etais pas clair.

Allez zou, un petit exemple de truc qui marche pas mal.
Regardez l’appli de test, ca devrait vous faire marrer ^^.

[quote=“girafologue, post:18, topic: 33785”]Allez zou, un petit exemple de truc qui marche pas mal.
Regardez l’appli de test, ca devrait vous faire marrer ^^.[/quote]

Bon ben voilà, c’était pas difficile quand même. Blague à part, c’est extra, fluide et tout. Me reste plus qu’à regarder comment ca marcher et le décliner pour mes besoins au moment voulu, mais je pense que ca va le faire grave. Merci beaucoup pour l’exemple illustré B)

WPF owns B)