Причины, по которым ярлык WinForms не хочет быть прозрачным? - PullRequest
27 голосов
/ 03 марта 2009

Почему я не могу установить для BackColor метки значение Transparent? Я делал это раньше, но сейчас просто не хочу ...

Я создал новый UserControl, добавил индикатор выполнения и метку к нему. Когда я устанавливаю прозрачный цвет метки BackColor, он остается серым = / Почему это так?

Я хотел, чтобы метка находилась в верхней части индикатора выполнения, чтобы ее текст находился «внутри» индикатора выполнения ...

Ответы [ 11 ]

31 голосов
/ 04 марта 2009

Добавьте новый класс в свой проект и опубликуйте код, показанный ниже. Построить. Перетащите новый элемент управления из верхней части панели инструментов на форму.

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;
    }
  }
}
14 голосов
/ 03 марта 2009

WinForms на самом деле не поддерживает прозрачные элементы управления, но вы можете создать прозрачный элемент управления самостоятельно. Смотрите мой ответ здесь .

В вашем случае вам, вероятно, следует создать подкласс индикатора выполнения и переопределить метод OnPaint, чтобы нарисовать текст на индикаторе выполнения.

7 голосов
/ 09 августа 2011

Самое простое решение следующее:

  1. Установите цвет фона для прозрачности либо в визуальном редакторе, либо в конструкторе вашей формы:

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

  2. Установите свойство Parent вашей метки, чтобы контролировать, что вы хотите видеть за текстом. Это можно сделать в конструкторе формы или в методе Load:

    this.label1.Parent = progressBar1;

Это правда, что это не настоящая прозрачность, как в DirectX. Результат, который вы видите на дисплее, состоит только из двух слоев. Этот подход не позволяет суммировать более двух слоев (каждый слой имеет свою прозрачность, определяемую альфа-параметром). Но он подходит для многих практических ситуаций, с которыми вы можете столкнуться при программировании Winforms.

4 голосов
/ 26 марта 2011

Используйте LinkLabel, а не нормальный ярлык

    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;
    }
1 голос
/ 12 февраля 2014

Это очень простое решение и прекрасно работает:

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);
    }
}

Когда задний цвет метки прозрачен, метка получает изображение своего базового элемента управления только при первом создании, после того как задний цвет метки является постоянным. И каждый раз, когда метка перерисовывается, она перекрашивается в этот фиксированный цвет или рисунок.

Переопределение CreateParams влияет на то, как будет создано окно для элемента управления, это обеспечивает реальную прозрачность.

Переопределяя WndProc, вы контролируете, какие сообщения следует передавать в базовый класс. Мы должны фильтровать WM_ERASEBKGND и WM_PAINT, но мы также должны вызвать событие рисования.

1 голос
/ 26 мая 2010

Вот прозрачный элемент управления, который я написал некоторое время назад, который отображает повернутый текст. Большая часть кода взята из здесь , хотя IIRC мне пришлось сделать несколько настроек, чтобы заставить его работать.

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);
        }
    }
}
1 голос
/ 03 марта 2009

Если вы хотите сосредоточиться на разработке приложения для Windows, я предлагаю вам использовать WPF.

Сделать WPR прозрачным в WPF очень просто.

<TextBox Width="200" Height="40" Opacity="0.5"/>
0 голосов
/ 13 февраля 2010

Выберите BackColor , перейдите на вкладку Интернет и выберите Прозрачный. Создает следующее.

        this.label1.BackColor = System.Drawing.Color.Transparent;
0 голосов
/ 05 октября 2009

что касается объяснения вашей проблемы, окна не обеспечивают прозрачность для фоновых элементов управления, как вы и ожидали - я предполагаю, что серый фон на самом деле является поверхностью формы. все элементы управления, нарисованные между поверхностью формы и надписью, игнорируются.

0 голосов
/ 05 октября 2009

Можно сделать именно то, что вы хотите достичь. Это займет немного времени, чтобы поиграть с элементами управления. Можно создать элемент управления Label с прозрачным фоном и поместить его поверх элемента управления Progressbar.

Проверьте мой ответ на еще один вопрос.

...