web-dev-qa-db-ja.com

WinFormsラベルが透明になりたくない理由は何ですか?

ラベルのBackColorを透明に設定できないのはなぜですか?私は以前にそれをしました、しかし今それはただしたくありません...

新しいUserControlを作成し、プログレスバーとラベルを追加しました。ラベルのBackColorを透明に設定しても、まだ灰色です= /これはなぜですか?

私が欲しかったのは、進行状況バーの上にラベルを付けて、そのテキストが進行状況バーの「中に」あるようにすることでした。

27
Svish

WinFormsは実際には透過的なコントロールをサポートしていませんが、自分で透過的なコントロールを作成することができます。 ここで私の答えを参照してください

あなたの場合、おそらくプログレスバーをサブクラス化し、OnPaintメソッドをオーバーライドしてプログレスバーにテキストを描画する必要があります。

14
Rune Grimstad

プロジェクトに新しいクラスを追加し、以下に示すコードを投稿します。ビルドします。ツールボックスの上部からフォームに新しいコントロールをドロップします。

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

最も簡単な解決策は次のとおりです。

  1. ビジュアルエディタまたはフォームのコンストラクタで、背景色を透明に設定します。

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

  2. ラベルのParentプロパティを設定して、テキストの後ろに表示するように制御します。これは、フォームコンストラクターまたはLoadメソッドで実行できます。

    this.label1.Parent = progressBar1;

これはDirectXのように真の透明性ではないのは事実です。表示される結果は、2つのレイヤーのみで構成されています。このアプローチでは、3つ以上のレイヤーを合計することはできません(各レイヤーには、アルファパラメーターによって定義された独自の透明度があります)。しかし、Winformsプログラミングで遭遇する可能性のある多くの実際的な状況に適しています。

7
truthseeker

通常のラベルではなく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;
    }
4

これは、回転したテキストを表示する、少し前に書いた透過的なコントロールです。ほとんどのコードは ここ から来ていますが、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);
        }
    }
}

Windowsアプリケーションの設計に集中したい場合は、WPFを使用することをお勧めします。

WPFでコントロールを透過的にするのは非常に簡単です。

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

これは非常に単純な解決策であり、うまく機能します。

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をフィルタリングする必要がありますが、Paintイベントもトリガーする必要があります。

1

あなたの問題の説明に関しては、ウィンドウはあなたが期待するように背景コントロールの透明度を行いません-私は灰色の背景が実際にはフォームの表面であると推測しています。フォームサーフェスとラベルの間に描画されるコントロールはすべて無視されます。

0
lincolnk

あなたが達成したいことを正確に行うことが可能です。コントロールで遊ぶのに少し時間がかかります。背景が透明なラベルコントロールを作成し、プログレスバーコントロールの上に配置することができます。

チェック 私の答え 別のSO質問。

0
MaciekTalaska

したがって、以前の回答へのコメントで述べたように、コントロールはデフォルトの動作であり、透過的であると私が覚えているものです。

とにかく、UserControlのbackgroundプロパティ、またはラベルが含まれているコンテナ(Panel、Formなど)を設定しようとしましたか?ラベルはその色を反映している必要があります:)


古い回答:winformsプログラミングを行ってからしばらく経ちましたが、覚えているように、ラベルはデフォルトで透過的ですか?したがって、実際の色を取得するのはそのテキストだけであり、背景色はその背後にあるものを模倣します:)

0
thmsn