web-dev-qa-db-fra.com

Pourquoi une étiquette WinForms ne veut-elle pas être transparente?

Pourquoi ne puis-je pas définir le BackColor d'une étiquette sur Transparent? Je l'ai déjà fait auparavant, mais maintenant il ne veut tout simplement pas ...

J'ai créé un nouveau UserControl, ajouté une barre de progression et une étiquette. Lorsque je règle le BackColor de l’étiquette sur transparent, il reste gris =/Pourquoi?

Ce que je voulais, c'était que l'étiquette se trouve en haut de la barre de progression afin que son texte soit "dans" la barre de progression ...

27
Svish

WinForms ne supporte pas vraiment les contrôles transparents, mais vous pouvez créer un contrôle transparent vous-même. Voir ma réponse ici .

Dans votre cas, vous devriez probablement sous-classer la barre de progression et remplacer la méthode OnPaint pour dessiner un texte sur la barre de progression.

14
Rune Grimstad

Ajoutez une nouvelle classe à votre projet et postez le code ci-dessous. Construire. Déposez le nouveau contrôle du haut de la boîte à outils sur votre formulaire.

using System;
using System.Windows.Forms;

public class TransparentLabel : Label {
  public TransparentLabel() {
    this.SetStyle(ControlStyles.Opaque, true);
    this.SetStyle(ControlStyles.OptimizedDoubleBuffer, false);
  }
  protected override CreateParams CreateParams {
    get {
      CreateParams parms = base.CreateParams;
      parms.ExStyle |= 0x20;  // Turn on WS_EX_TRANSPARENT
      return parms;
    }
  }
}
31
Hans Passant

La solution la plus simple est la suivante:

  1. Définissez la couleur d'arrière-plan sur la transparence dans l'éditeur visuel ou dans le constructeur de votre formulaire:

    this.label1.BackColor = System.Drawing.Color.Transparent;

  2. Définissez la propriété Parent de votre étiquette pour indiquer que vous souhaitez être visible derrière le texte. Cela peut être fait dans le constructeur de formulaire ou dans la méthode Load:

    this.label1.Parent = progressBar1;

Il est vrai que ce n’est pas la vraie transparence comme dans DirectX. Le résultat que vous voyez à l'écran est composé uniquement de deux couches. Vous ne pouvez pas résumer plus de deux couches avec cette approche (chaque couche ayant sa propre transparence définie par un paramètre alpha). Mais il convient à de nombreuses situations pratiques que vous pouvez rencontrer dans la programmation Winforms.

7
truthseeker

Utilisez un LinkLabel pas une étiquette normale

    private void MakeTransparentLabel(System.Windows.Forms.LinkLabel LinkLabel)
    {
        this.MakeTransparentLabel(LinkLabel, Color.White);
    }
    private void MakeTransparentLabel(System.Windows.Forms.LinkLabel LinkLabel, Color ForeColor)
    {
        LinkLabel.ForeColor = ForeColor;
        LinkLabel.LinkColor = ForeColor;
        LinkLabel.VisitedLinkColor = ForeColor;
        LinkLabel.ActiveLinkColor = ForeColor;
        LinkLabel.DisabledLinkColor = ForeColor;
        LinkLabel.LinkArea = new LinkArea(0, 0);
        LinkLabel.LinkBehavior = LinkBehavior.NeverUnderline;
        LinkLabel.Cursor = Cursors.Arrow;
        LinkLabel.BackColor = Color.Transparent;
    }
    private void SetTransparentLabelText(System.Windows.Forms.LinkLabel LinkLabel, string Text)
    {
        if (string.IsNullOrEmpty(Text)) { LinkLabel.Text = " "; return; }
        LinkLabel.Text = Text;
    }
4
alexander willemse

Voici un contrôle transparent que j'ai écrit il y a quelque temps et qui affiche du texte pivoté. La plupart du code provient de ici , bien que l'IIRC ait dû faire quelques ajustements pour qu'il fonctionne.

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Linq;
using System.Windows.Forms;

namespace MyNamespace
{
    public partial class RotatedText : UserControl
    {
        private readonly Timer _invalidationTimer;
        private const int WS_EX_TRANSPARENT = 0x00000020;

        public RotatedText()
        {
            this.SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            InitializeComponent();

            _invalidationTimer = new Timer {Interval = 500, Enabled = true};
            _invalidationTimer.Tick += TickHandler;
        }

        [Browsable(true)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        [Category("Appearance")]
        [Description("Text which appears in control")]
        public string Text { get; set; }

        #region Transparent background
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= WS_EX_TRANSPARENT;
                return cp;
            }
        }

        private void TickHandler(object sender, EventArgs e)
        {
            InvalidateEx();
        }

        private void InvalidateEx()
        {
            if (Parent != null)
                Parent.Invalidate(Bounds, false);
            else
                Invalidate();
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
            //Intentionally do nothing - stops background from drawing
            //base.OnPaintBackground(e);
        } 
        #endregion

        //Rotate text and draw
        protected override void OnPaint(PaintEventArgs e)
        {
            double angleRadians = Math.Atan2(Height, Width);
            float angleDegrees = -1*(float) (angleRadians*180/Math.PI);
            angleDegrees *= 0.9f;
            e.Graphics.RotateTransform(angleDegrees, MatrixOrder.Append);
            e.Graphics.TranslateTransform(20, Height - 75, MatrixOrder.Append);
            e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
            Font font = new Font("Ariel", 50);
            e.Graphics.DrawString(Text, font, Brushes.Gray, 1, 2); //Shadow
            e.Graphics.DrawString(Text, font, Brushes.Red, 0, 0);
        }
    }
}

Si vous souhaitez vous concentrer sur la conception de votre application Windows, je vous suggère d'utiliser WPF.

Rendre les contrôles transparents dans WPF est très facile.

<TextBox Width="200" Height="40" Opacity="0.5"/>
1
はると

Ceci est une solution très simple et fonctionne très bien:

public class MyLabel : Label
{
    private bool fTransparent = false;
    public bool Transparent
    {
        get { return fTransparent; }
        set { fTransparent = value; }
    }
    public MyLabel() : base()
    {
    }
    protected override CreateParams CreateParams
    {
        get
        {
            if (fTransparent)
            {
                CreateParams cp = base.CreateParams;
                cp.ExStyle |= 0x00000020; //WS_EX_TRANSPARENT
                return cp;
            }
            else return base.CreateParams;
        }
    }
    protected override void WndProc(ref Message m)
    {
        if (fTransparent)
        {
            if (m.Msg != 0x14 /*WM_ERASEBKGND*/ && m.Msg != 0x0F /*WM_Paint*/)
                base.WndProc(ref m);
            else 
            {
                if (m.Msg == 0x0F) // WM_Paint
                    base.OnPaint(new PaintEventArgs(Graphics.FromHwnd(Handle), ClientRectangle));
                DefWndProc(ref m);
            }
        }
        else base.WndProc(ref m);
    }
}

Lorsque la couleur de fond de l'étiquette est transparente, elle ne prend en photo le contrôle sous-jacent que lors de sa première création, une fois que cette couleur est constante. Et chaque fois que l'étiquette se repeint, elle repeint à cette couleur ou motif fixe.

Le remplacement de CreateParams affecte la manière dont la fenêtre de contrôle sera créée, ce qui permet une réelle transparence.

En remplaçant WndProc, vous contrôlez les messages à transmettre à la classe de base. Nous devons filtrer WM_ERASEBKGND et WM_Paint, mais nous devons également déclencher l'événement Paint.

1
Elvedin Hamzagic

en ce qui concerne l'explication de votre problème, Windows ne fait pas la transparence des contrôles d'arrière-plan comme prévu, je suppose que l'arrière-plan gris correspond en réalité à la surface du formulaire. quels que soient les contrôles dessinés entre la surface du formulaire et votre étiquette sont ignorés.

0
lincolnk

Il est possible de faire exactement ce que vous voulez réaliser. Cela prend juste un peu de temps pour jouer avec les contrôles. Il est possible de créer un contrôle Label avec un arrière-plan transparent et de le placer au-dessus du contrôle Progressbar.

Vérifiez ma réponse à une autre SO question.

0
MaciekTalaska

Donc, comme indiqué dans le commentaire de ma réponse précédente, le contrôle est le comportement par défaut et correspond à ce que je me rappelais comme étant transparent.

Quoi qu'il en soit, avez-vous essayé de définir la propriété background de votre UserControl ou le conteneur dans lequel se trouve votre étiquette (Panneau, Formulaire, peu importe?), Votre étiquette doit refléter cette couleur :)


Ancienne réponse: Cela fait longtemps que je n’ai pas programmé Winforms, mais comme je me souviens bien, les étiquettes sont transparentes par défaut? Ainsi, seul le texte prend une couleur réelle et la couleur de base imite ce qui se cache derrière.

0
thmsn