38 votes

Couleurs multiples dans une étiquette C# .NET

Je cherche un moyen d'afficher plusieurs couleurs dans une seule étiquette C#/.NET. Par exemple, l'étiquette affiche une série de valeurs séparées par un csv, qui prennent chacune une couleur en fonction de la catégorie dans laquelle elles se trouvent. Je préférerais ne pas utiliser plusieurs étiquettes, car les valeurs sont de longueur variable et je ne veux pas jouer avec des mises en page dynamiques. Existe-t-il un support natif pour cela ?

45voto

MusiGenesis Points 49273

Il n'existe pas de contrôle natif dans .NET qui permette de faire cela. Votre meilleure chance est d'écrire votre propre UserControl (appelez-le RainbowLabel ou autre). Normalement, le contrôle d'étiquette personnalisé devrait hériter directement de Label, mais comme il est impossible d'obtenir un texte multicolore dans une seule étiquette, il suffit d'hériter de UserControl.

Pour le rendu du texte, votre UserControl pourrait diviser le texte en virgules et charger dynamiquement une étiquette de couleur différente pour chaque fragment. Toutefois, une meilleure méthode consiste à rendre le texte directement sur votre UserControl à l'aide des méthodes DrawString et MeasureString de l'espace de noms Graphics.

Il n'est vraiment pas difficile d'écrire des commandes utilisateur dans .NET, et ce type de problème inhabituel est exactement le but des commandes utilisateur personnalisées.

Mise à jour Voici une méthode simple que vous pouvez utiliser pour rendre le texte multicolore d'une PictureBox :

public void RenderRainbowText(string Text, PictureBox pb)
{
    // PictureBox needs an image to draw on
    pb.Image = new Bitmap(pb.Width, pb.Height);
    using (Graphics g = Graphics.FromImage(pb.Image))
    {
        // create all-white background for drawing
        SolidBrush brush = new SolidBrush(Color.White);
        g.FillRectangle(brush, 0, 0,
            pb.Image.Width, pb.Image.Height);
        // draw comma-delimited elements in multiple colors
        string[] chunks = Text.Split(',');
        brush = new SolidBrush(Color.Black);
        SolidBrush[] brushes = new SolidBrush[] { 
            new SolidBrush(Color.Red),
            new SolidBrush(Color.Green),
            new SolidBrush(Color.Blue),
            new SolidBrush(Color.Purple) };
        float x = 0;
        for (int i = 0; i < chunks.Length; i++)
        {
            // draw text in whatever color
            g.DrawString(chunks[i], pb.Font, brushes[i], x, 0);
            // measure text and advance x
            x += (g.MeasureString(chunks[i], pb.Font)).Width;
            // draw the comma back in, in black
            if (i < (chunks.Length - 1))
            {
                g.DrawString(",", pb.Font, brush, x, 0);
                x += (g.MeasureString(",", pb.Font)).Width;
            }
        }
    }
}

Évidemment, cela ne fonctionnera pas si vous avez plus de 4 éléments séparés par des virgules dans votre texte, mais vous voyez l'idée. De plus, il semble y avoir un petit problème dans MeasureString qui lui fait renvoyer une largeur de quelques pixels plus large que nécessaire, de sorte que la chaîne multicolore semble étirée - vous pourriez vouloir modifier cette partie.

Il devrait être facile de modifier ce code pour un UserControl.

Note : TextRenderer est une meilleure classe à utiliser pour dessiner et mesurer des chaînes de caractères, car elle utilise des ints. Graphics.DrawString et .MeasureString utilisent des flottants, et vous aurez donc des erreurs à un pixel près ici et là.

Mise à jour : Oubliez sur l'utilisation de TextRenderer. Il est très lent.

4 votes

Héritant de Control pourrait avoir plus de sens que de UserControl si le contrôle doit se dessiner lui-même.

16voto

Phil Wright Points 11696

Vous pourriez essayer d'utiliser une RichTextBox afin d'obtenir plusieurs couleurs pour la chaîne de caractères, puis la rendre en lecture seule et supprimer la bordure. Changez la couleur d'arrière-plan pour qu'elle soit identique à celle du formulaire sur lequel elle se trouve et vous pourriez vous en sortir.

5voto

Marc Gravell Points 482669

Vous pouvez également le faire en format rtf ou html dans un contrôle approprié (tel que WebBrowser). Cela nécessitera probablement un peu plus de ressources que vous ne le souhaiteriez, mais cela fonctionnera assez rapidement.

0 votes

Très bonne idée. En définissant la couleur de fond du navigateur Web comme celle du formulaire et en masquant les barres de défilement, on peut faire en sorte que le formulaire ressemble à une étiquette. Quelque chose comme ceci : Color color = this.BackColor; string text = string.Format("<style> body {{ background-color: rgb({0},{1},{2}) }}</style> Hello, <b>every</b><i>one</i>!</div>", color.R, color.G, color.B); webBrowser1.DocumentText = text; avec webBrowser1.ScrollBarsEnabled = false; le rendre génial.

4voto

Timothy Khouri Points 14640

Si vous créez votre application Windows pour les utilisateurs de XP et plus, vous pouvez utiliser WPF. Même s'il s'agit d'une application Windows Forms, vous pouvez ajouter un UserControl WPF.

J'utiliserais alors une étiquette, et je définirais la propriété "Foreground" (avant-plan) comme étant un gradient de couleurs.

Ou, dans Windows Forms (pas WPF), vous pouvez simplement utiliser un "Flow Panel", et ensuite, dans une boucle for, ajouter plusieurs étiquettes comme segments de votre message... elles "couleront" toutes ensemble comme s'il s'agissait d'une seule étiquette.

1voto

YordanGeorgiev Points 1222

Légèrement hors sujet ... Vous pouvez également vérifier :

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X