Проблема прозрачности перекрывающихся PictureBox на C # - PullRequest
4 голосов
/ 05 августа 2009

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

Проблема в том, что нижний слой не виден, прозрачное изображение, показывает земля панели. Исключением является то, что видно нижнее изображение PictureBox.

Я пытался сделать это с другими элементами управления, такими как label. Проблема не может быть решена: (

Спасибо.

Ответы [ 4 ]

11 голосов
/ 05 августа 2009

Это потому, что, если я правильно помню, установка цвета фона Transparent (его фактическое значение равно нулю, верно?) Не является действительно прозрачным. Что делает Windows, так это смотрит на цвет фона родительского контейнера элемента управления и устанавливает для него цвет фона элемента управления.

Вы можете видеть это, особенно с панелями. Без содержимого панели с прозрачностью должны позволять вам видеть за ними, верно? Неправильно. Если вы поместите панель поверх, скажем, элементов управления текстовым полем и установите для нее значение «Прозрачный», вы не сможете видеть текстовые поля за ней.

Вместо этого, чтобы получить реальную прозрачность, вы должны перегрузить OnPaintBackground для рассматриваемого элемента управления и, по сути, абсолютно ничего не делать (НЕ вызывайте и base.OnPainBackground!) ... Это больше, чем это, возможно , но вот пример рабочего элемента управления TransparentPanel, который мы используем здесь:

public class TransparentPanel : System.Windows.Forms.Panel
{
    [Browsable(false)]
    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x20;
            return cp;
        }
    }
    protected override void OnPaintBackground(PaintEventArgs e)
    {
        // Do Nothing
    }
}

Мы успешно использовали этот класс для создания действительно прозрачных панелей в прошлых приложениях Windows Forms. Мы использовали его как хак для исправления проблемы «контекстное меню, вызываемое правой кнопкой мыши, появляется над кнопками».

5 голосов
/ 05 августа 2009

Это мое мнение:

class TransPictureBox : Control
{
    private Image _image = null;

    public Image Image
    {
        get
        {
            return _image;
        }
        set
        {
            _image = value;
        }
    }
    public TransPictureBox()
    {
    }

    protected override void OnPaintBackground(PaintEventArgs pevent)
    {
    }

    protected override void OnPaint(PaintEventArgs pe)
    {
        if(Image != null)
            pe.Graphics.DrawImage(Image, 0, 0);
    }
    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x20;
            return cp;
        }
    }
}

Вы должны добавить больше логики для позиционирования изображения по своему желанию и соответствующим образом отредактировать метод OnPaint.

2 голосов
/ 22 декабря 2010

Я смог сделать это в VB. Есть несколько хитростей, хотя. Прежде всего вы должны добавить графические блоки друг к другу. Во-вторых, изображения в графических полях должны быть PNG.

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

Imports System.Drawing
Imports System.Drawing.Imaging
Imports System

Public Class Form1

    Dim MarkerBox1 As New PictureBox
    Dim MarkerBox2 As New PictureBox
    Dim MarkerBox3 As New PictureBox

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        PictureBox1.Image = New Bitmap("C:\BackGround.bmp")

        MarkerBox1.Image = New Bitmap("C:\TestOverlay1.png")
        MarkerBox1.BackColor = System.Drawing.Color.Transparent
        MarkerBox1.Visible = True
        MarkerBox1.SizeMode = PictureBoxSizeMode.AutoSize
        PictureBox1.Controls.Add(MarkerBox1)

        MarkerBox2.Image = New Bitmap("C:\TestOverlay2.png")
        MarkerBox2.BackColor = System.Drawing.Color.Transparent
        MarkerBox2.Visible = True
        MarkerBox2.SizeMode = PictureBoxSizeMode.AutoSize
        MarkerBox1.Controls.Add(MarkerBox2)

        MarkerBox3.Image = New Bitmap("C:\TestOverlay3.png")
        MarkerBox3.BackColor = System.Drawing.Color.Transparent
        MarkerBox3.Visible = True
        MarkerBox3.SizeMode = PictureBoxSizeMode.AutoSize
        MarkerBox2.Controls.Add(MarkerBox3)


    End Sub

    Private Sub CheckBox1_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox1.CheckedChanged
        If CheckBox1.Checked Then
            MarkerBox1.Visible = True
        Else
            MarkerBox1.Visible = False
        End If
        Visibilitychanged()
    End Sub

    Private Sub CheckBox2_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox2.CheckedChanged
        If CheckBox2.Checked Then
            MarkerBox2.Visible = True
        Else
            MarkerBox2.Visible = False
        End If
        Visibilitychanged()
    End Sub

    Private Sub CheckBox3_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CheckBox3.CheckedChanged
        If CheckBox3.Checked Then
            MarkerBox3.Visible = True
        Else
            MarkerBox3.Visible = False
        End If
        Visibilitychanged()
    End Sub

    Private Sub Visibilitychanged()

        PictureBox1.Controls.Clear()
        MarkerBox1.Controls.Clear()
        MarkerBox2.Controls.Clear()
        MarkerBox3.Controls.Clear()

        Dim PB As PictureBox = PictureBox1
        If MarkerBox1.Visible Then
            PB.Controls.Add(MarkerBox1)
            PB = MarkerBox1
        End If
        If MarkerBox2.Visible Then
            PB.Controls.Add(MarkerBox2)
            PB = MarkerBox2
        End If
        If MarkerBox3.Visible Then
            PB.Controls.Add(MarkerBox3)
            PB = MarkerBox3
        End If

    End Sub
0 голосов
/ 13 октября 2009

Вы должны сделать

pe.Graphics.DrawImage(Image, 0, 0, Image.Width, Image.Height);

чтобы ваше изображение не растягивалось

...