C # Picturebox прозрачный фон не работает - PullRequest
18 голосов
/ 02 апреля 2011

Для моего проекта мне нужны изображения для отображения с прозрачным фоном.Я сделал несколько изображений .png с прозрачным фоном (чтобы проверить это, я открыл их в Photoshop).Теперь у меня есть класс, который расширяет PictureBox:

class Foo : PictureBox
{
    public Foo(int argument)
        : base()
    {
        Console.WriteLine(argument);//different in the real application of course.
        //MyProject.Properties.Resources.TRANSPARENCYTEST.MakeTransparent(MyProject.Properties.Resources.TRANSPARENCYTEST.GetPixel(1,1)); //<-- also tried this
        this.Image = MyProject.Properties.Resources.TRANSPARENCYTEST;
        ((Bitmap)this.Image).MakeTransparent(((Bitmap)this.Image).GetPixel(1, 1));
        this.SizeMode = PictureBoxSizeMode.StretchImage;
        this.BackColor = System.Drawing.Color.Transparent;
    }
}

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

Ответы [ 6 ]

38 голосов
/ 06 февраля 2012

Если вы хотите наложить изображения на изображения (а не на изображения поверх формы), это поможет:

overImage.Parent = backImage;
overImage.BackColor = Color.Transparent;
overImage.Location = thePointRelativeToTheBackImage;

Где overImage и backImage - PictureBox с png (с прозрачным фоном).

Это потому, что, как уже было сказано, прозрачность изображения отображается с использованием заднего цвета родительского контейнера.PictureBoxes не имеют свойства «Parent», поэтому вы должны сделать это вручную (или, конечно, создать элемент управления Cutom).

20 голосов
/ 02 апреля 2011

Это, вероятно, работает отлично. Вы видите, что скрывается за блоком управления изображением. Который является формой. Чей BackColor, вероятно, белый. Вы можете установить свойство BackgroundImage формы, чтобы быть уверенным, что вы должны видеть изображение через графическое поле. Как это:

enter image description here

Пробивание отверстия через и графическое поле и форма требует большего оружия, Form.TransparencyKey

12 голосов
/ 12 сентября 2012

На веб-сайте CodeProject есть отличное решение:

Создание прозрачных элементов управления - без мерцания

По сути, трюк состоит в том, чтобы переопределить событие paintbackground, чтобы проходить по циклувсе элементы управления, лежащие в картинке, и перерисовать их.Функция: -

protected override void OnPaintBackground(PaintEventArgs e)
       // Paint background with underlying graphics from other controls
   {
       base.OnPaintBackground(e);
       Graphics g = e.Graphics;

       if (Parent != null)
       {
           // Take each control in turn
           int index = Parent.Controls.GetChildIndex(this);
           for (int i = Parent.Controls.Count - 1; i > index; i--)
           {
               Control c = Parent.Controls[i];

               // Check it's visible and overlaps this control
               if (c.Bounds.IntersectsWith(Bounds) && c.Visible)
               {
                   // Load appearance of underlying control and redraw it on this background
                   Bitmap bmp = new Bitmap(c.Width, c.Height, g);
                   c.DrawToBitmap(bmp, c.ClientRectangle);
                   g.TranslateTransform(c.Left - Left, c.Top - Top);
                   g.DrawImageUnscaled(bmp, Point.Empty);
                   g.TranslateTransform(Left - c.Left, Top - c.Top);
                   bmp.Dispose();
               }
           }
       }
   }
4 голосов
/ 15 октября 2013

Я знаю, что ваш вопрос основан на C # , но из-за сходства и простоты преобразования из VB.NET я добавлю полный VB *Версия 1006 *, которая также позволяет обновлять фон элемента управления при его перемещении.

У вас уже есть ответ, но это для тех, кто находит этот пост поисковыми системами и хочет VB версии, или просто хотите найти ПОЛНЫЙ конвертируемый образец, если он им также нужен в C # .

Создайте новый Пользовательский класс управления и вставьтеследуя ему ... перезаписываем класс по умолчанию:

Пользовательский класс управления:

Public Class TransparentPictureBox
    Private WithEvents refresher As Timer
    Private _image As Image = Nothing

    Public Sub New()

        ' This call is required by the designer.
        InitializeComponent()

        ' Add any initialization after the InitializeComponent() call.
        refresher = New Timer()
        'refresher.Tick += New EventHandler(AddressOf Me.TimerOnTick)
        refresher.Interval = 50
        refresher.Start()

    End Sub

    Protected Overrides ReadOnly Property CreateParams() As CreateParams
        Get
            Dim cp As CreateParams = MyBase.CreateParams
            cp.ExStyle = cp.ExStyle Or &H20
            Return cp
        End Get
    End Property

    Protected Overrides Sub OnMove(ByVal e As EventArgs)
        MyBase.OnMove(e)
        MyBase.RecreateHandle()
    End Sub

    Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
        MyBase.OnPaint(e)

        'Add your custom paint code here
        If _image IsNot Nothing Then
            e.Graphics.DrawImage(_image, CInt(Width / 2) - CInt(_image.Width / 2), CInt(Height / 2) - CInt(_image.Height / 2))
        End If
    End Sub


    Protected Overrides Sub OnPaintBackground(ByVal e As System.Windows.Forms.PaintEventArgs)
        ' Paint background with underlying graphics from other controls
        MyBase.OnPaintBackground(e)
        Dim g As Graphics = e.Graphics

        If Parent IsNot Nothing Then
            ' Take each control in turn
            Dim index As Integer = Parent.Controls.GetChildIndex(Me)
            For i As Integer = Parent.Controls.Count - 1 To index + 1 Step -1
                Dim c As Control = Parent.Controls(i)

                ' Check it's visible and overlaps this control
                If c.Bounds.IntersectsWith(Bounds) AndAlso c.Visible Then
                    ' Load appearance of underlying control and redraw it on this background
                    Dim bmp As New Bitmap(c.Width, c.Height, g)
                    c.DrawToBitmap(bmp, c.ClientRectangle)
                    g.TranslateTransform(c.Left - Left, c.Top - Top)
                    g.DrawImageUnscaled(bmp, Point.Empty)
                    g.TranslateTransform(Left - c.Left, Top - c.Top)
                    bmp.Dispose()
                End If
            Next
        End If
    End Sub

    Public Property Image() As Image
        Get
            Return _image
        End Get
        Set(value As Image)
            _image = value
            MyBase.RecreateHandle()
        End Set
    End Property

    Private Sub refresher_Tick(sender As Object, e As System.EventArgs) Handles refresher.Tick
        MyBase.RecreateHandle()
        refresher.Stop()
    End Sub
End Class

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

У меня были проблемы с этим элементом управления, хотя ... Это происходит, когда я пытаюсь загрузить анимированное изображение "Загрузка" .gif .

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

Разберитесь с этими проблемами, и у вас получится отличный класс пользовательского элемента управления,:)

РЕДАКТИРОВАТЬ:

Я не знаю, будет ли работать следующее в IDE C # или нет, но вот моя попыткапреобразование:

using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
public class TransparentPictureBox
{
    private Timer withEventsField_refresher;
    private Timer refresher {
        get { return withEventsField_refresher; }
        set {
            if (withEventsField_refresher != null) {
                withEventsField_refresher.Tick -= refresher_Tick;
            }
            withEventsField_refresher = value;
            if (withEventsField_refresher != null) {
                withEventsField_refresher.Tick += refresher_Tick;
            }
        }
    }

    private Image _image = null;

    public TransparentPictureBox()
    {
        // This call is required by the designer.
        InitializeComponent();

        // Add any initialization after the InitializeComponent() call.
        refresher = new Timer();
        //refresher.Tick += New EventHandler(AddressOf Me.TimerOnTick)
        refresher.Interval = 50;
        refresher.Start();

    }

    protected override CreateParams CreateParams {
        get {
            CreateParams cp = base.CreateParams;
            cp.ExStyle = cp.ExStyle | 0x20;
            return cp;
        }
    }

    protected override void OnMove(EventArgs e)
    {
        base.OnMove(e);
        base.RecreateHandle();
    }

    protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
    {
        base.OnPaint(e);

        //Add your custom paint code here
        if (_image != null) {
            e.Graphics.DrawImage(_image, Convert.ToInt32(Width / 2) - Convert.ToInt32(_image.Width / 2), Convert.ToInt32(Height / 2) - Convert.ToInt32(_image.Height / 2));
        }
    }


    protected override void OnPaintBackground(System.Windows.Forms.PaintEventArgs e)
    {
        // Paint background with underlying graphics from other controls
        base.OnPaintBackground(e);
        Graphics g = e.Graphics;

        if (Parent != null) {
            // Take each control in turn
            int index = Parent.Controls.GetChildIndex(this);
            for (int i = Parent.Controls.Count - 1; i >= index + 1; i += -1) {
                Control c = Parent.Controls(i);

                // Check it's visible and overlaps this control
                if (c.Bounds.IntersectsWith(Bounds) && c.Visible) {
                    // Load appearance of underlying control and redraw it on this background
                    Bitmap bmp = new Bitmap(c.Width, c.Height, g);
                    c.DrawToBitmap(bmp, c.ClientRectangle);
                    g.TranslateTransform(c.Left - Left, c.Top - Top);
                    g.DrawImageUnscaled(bmp, Point.Empty);
                    g.TranslateTransform(Left - c.Left, Top - c.Top);
                    bmp.Dispose();
                }
            }
        }
    }

    public Image Image {
        get { return _image; }
        set {
            _image = value;
            base.RecreateHandle();
        }
    }

    private void refresher_Tick(object sender, System.EventArgs e)
    {
        base.RecreateHandle();
        refresher.Stop();
    }
}

Попробуйте и убедитесь сами, я думаю: P

ps: я не гуру, так что ожидайте всевозможных ошибок в C #, иВерсии VB.NET.лол

3 голосов
/ 02 апреля 2011

Если вы отображаете png с прозрачностью в графическом окне, оно будет автоматически учитывать прозрачность, поэтому вам не нужно устанавливать прозрачный цвет

1 голос
/ 23 мая 2014

Ответы выше, похоже, решают вашу проблему.Вы действительно видите, что скрывается за элементом управления графическим блоком - сама форма с белым цветом backColor.Здесь я создал простую функцию, которая сначала преобразует изображение байтового типа (массив) в растровое изображение, а затем устанавливает конкретные цвета (из растрового изображения) в прозрачные.То, что вы могли бы также использовать:

 using System;
   using System.Drawing;
   using System.Drawing.Imaging;
   using System.Windows.Forms;
    public void LogoDrawTransparent(PaintEventArgs e)
    {
        // Create a Bitmap object from an image file.
        Image myImg;
        Bitmap myBitmap;

        try
        {
            myImg = cls_convertImagesByte.GetImageFromByte(newImg);
            myBitmap = new Bitmap(myImg); // @"C:\Temp\imgSwacaa.jpg");  

            // Get the color of a background pixel.
            Color backColor = myBitmap.GetPixel(0, 0); // GetPixel(1, 1); 
            Color backColorGray = Color.Gray;
            Color backColorGrayLight = Color.LightGray;
            Color backColorWhiteSmoke = Color.WhiteSmoke;
            Color backColorWhite = Color.White;
            Color backColorWheat = Color.Wheat;

            // Make backColor transparent for myBitmap.
            myBitmap.MakeTransparent(backColor);
                    // OPTIONALLY, you may make any other "suspicious" back color transparent (usually gray, light gray or whitesmoke)
            myBitmap.MakeTransparent(backColorGray);
            myBitmap.MakeTransparent(backColorGrayLight);
            myBitmap.MakeTransparent(backColorWhiteSmoke);

            // Draw myBitmap to the screen.
            e.Graphics.DrawImage(myBitmap, 0, 0, pictureBox1.Width, pictureBox1.Height); //myBitmap.Width, myBitmap.Height);
        }
        catch
        {
            try { pictureBox1.Image = cls_convertImagesByte.GetImageFromByte(newImg); }
            catch { } //must do something
        }
    }

Вы можете использовать эту функцию в Paint of the PictureBox.Это мой класс, на который ссылается функция выше:

    class cls_convertImagesByte
{

    public static Image GetImageFromByte(byte[] byteArrayIn)
    {
        MemoryStream ms = new MemoryStream(byteArrayIn);
        Image returnImage = Image.FromStream(ms);
        return returnImage;
    }

    public static byte[] GetByteArrayFromImage(System.Drawing.Image imageIn)
    {
        MemoryStream ms = new MemoryStream();
        imageIn.Save(ms, System.Drawing.Imaging.ImageFormat.Gif);
        return ms.ToArray();
    }
}

Спасибо.Chagbert

...