Подтвердить что ты не робот

С# Picturebox прозрачный фон, похоже, не работает

Для моего проекта мне нужны изображения для отображения с прозрачным фоном. Я сделал некоторые .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;
    }
}

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

4b9b3361

Ответ 1

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

enter image description here

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

Ответ 2

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

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

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

Это происходит потому, что, как говорилось ранее, прозрачность изображения визуализируется с использованием заднего цвета родительского контейнера. PictureBoxes не имеют свойства "Родитель", поэтому вам нужно сделать это вручную (или, конечно же, создать элемент управления cutom).

Ответ 3

Отличное решение на веб-сайте 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 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

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

У вас уже есть ответ, но это касается других, которые находят это сообщение в поисковых системах и хотели бы иметь версию VB или просто хотят найти FULL конвертируемый образец, если они также нуждаются в нем в С#.

Создайте новый Custom Control Class и вставьте в него следующее: перезаписывайте материал класса по умолчанию:

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

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 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.

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

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

EDIT:

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

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 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: Я не гуру, поэтому ожидайте всевозможные ошибки в версиях С# и VB.NET. лол

Ответ 5

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

Ответ 6

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

 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. Это мой класс, на который ссылается n выше:

    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