且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

使 png 图像透明

更新时间:2023-11-10 20:53:16

您可能知道,WinForms 控件的设计并不完全支持真正的透明度(Forms 除外,那些实际上可以是透明的).

位图,另一方面,支持透明度.
如果您使用支持 Alpha 通道的图像格式(如 .png 位图)创建 Bitmap 对象,则可以绘制该图像并保留其透明度.
>

首先要做的是创建一个对象,该对象可用于引用我们要绘制的每个Bitmap,以便我们可以跟踪它们.
由于您希望能够指定这些对象的位置和大小,这是对象必须具有的两个属性.我将在此处添加一些有用的内容.

公共类位图对象公共属性名称作为字符串公共属性图像作为位图公共财产定位为点公共财产大小作为大小公共财产顺序为整数结束班

属性 Name 将是源文件的名称,Order 将引用 Bitmap 相对于在容器内绘制的其他位图.
所有 Bitmaps 都将使用 Bitmap 对象列表进行分组,因此我们可以使用列表索引或其中一个属性来调用它们.

公共MyBitmaps作为列表(BitmapObject)=新列表(BitmapObject)

至于绘图表面(画布),我们可以使用 Form 本身、PictureBoxPanel(因为它们是- 或多或少 - 只是表面).我更喜欢 Panel,它很轻巧,可以承载其他控件,并且可以在需要时四处移动.

如果你想在一个控件上绘图,你只需要订阅它的 Paint() 事件并调用控件的 Invalidate() 方法引发它.

Private Sub Panel1_Paint(sender As Object, e As PaintEventArgs) 处理 Panel1.Paint如果 MyBitmaps.Count >0 那么MyBitmaps.OrderBy(Function(item) item.Order).选择(功能(项目)e.Graphics.DrawImage(item.Image, New Rectangle(item.Position, item.Size))归还物品结束函数).ToList()万一结束子

要将 Bitmap 添加到 List(Of BitmapObject),因为您想使用 OpenFileDialog 让用户选择一个 Bitmap,我们将此功能分配给 Button,当 Bitmap 被选中时,会创建并附加一个新的 BitmapObject到列表.

Private Sub btnOpenFile_Click(sender As Object, e As EventArgs) 处理 btnOpenFile.ClickDim fd As OpenFileDialog = New OpenFileDialog()fd.InitialDirectory = "[图片路径]"Dim dr As DialogResult = fd.ShowDialog()如果 dr = Windows.Forms.DialogResult.OK 那么Dim BitmapName As String = New FileInfo(fd.FileName).Name使用 tmpBitmap As Bitmap = New Bitmap(fd.FileName)MyBitmaps.Add(New BitmapObject with {.Image = New Bitmap(tmpBitmap),.Position = New Point(Integer.Parse(TextBox1.Text), Integer.Parse(TextBox2.Text)),.Size = New Size(tmpBitmap.Height, tmpBitmap.Width),.Order = MyBitmaps.Count,.Name = BitmapName})ComboBox1.Items.Add(BitmapName)ComboBox1.SelectedIndex = MyBitmaps.Count - 1TrackBar1.Value = tmpBitmap.HeightTrackBar2.Value = tmpBitmap.WidthPanel1.Invalidate()结束使用万一结束子

这是结果:(

I have a PictureBox added to my Panel1 with Panel1.Controls.Add(pb), and I have tried to make my .png picture transparent.
I have tried with Color.Transparent and with System.Drawing.Color.Transparent, but when I add the PictureBox to my Panel, I can not make it transparent.

And also I'm not able to bring to the front of the others images.

This is my code.

Private Function molduraint()

    Dim pb As New PictureBox

    pb.BringToFront()
    pb.ImageLocation = OpenFileDialog1.FileName
    pb.SizeMode = PictureBoxSizeMode.StretchImage

    Panel1.Controls.Add(pb)

    pb.Location = New Point(txtValueX.Text, txtValueY.Text)
    If txtValueX.Text = 0 Or txtValueY.Text = 0 Then
        pb.Location = New Point(300, 172)
    End If

    pb.Visible = True
    pb.Size = New Size(TrackBar1.Value, TrackBar2.Value)
    pb.Image = PictureBox1.Image

End Function

As you probably know, WinForms controls are not exactly designed to support true transparency (except Forms, those can be actually transparent).

Bitmaps, on the other hand, support transparency.
If you create a Bitmap object using an image format that supports an Alpha Channel, like a .png bitmap, you can draw that image preserving its transparency.

The first thing to do is to create an object that can be used to reference each Bitmap we want to draw, so we can keep track of them.
Since you want to be able to specify position and size of these objects, those are two of the properties that the object must have. I'm adding some more that can be helpful here.

Public Class BitmapObject
    Public Property Name As String
    Public Property Image As Bitmap
    Public Property Position As Point
    Public Property Size As Size
    Public Property Order As Integer
End Class

The property Name will be the name of source file and Order will reference the z-order position of the Bitmap in relation to the other Bitmaps drawn inside a container.
All the Bitmaps will be grouped using a List of Bitmap objects, so we can summon them using the List Index or one of the properties.

Public MyBitmaps As List(Of BitmapObject) = New List(Of BitmapObject)

As for the drawing surface (canvas), we can use the Form itself, a PictureBox or a Panel (because they're - more or less - just surfaces). I prefer a Panel, it's lightweight, it can host other controls and can be moved around if needed.

If you want to draw on a control, you just need to subscribe its Paint() event and raise it calling the control's Invalidate() method.

Private Sub Panel1_Paint(sender As Object, e As PaintEventArgs) Handles Panel1.Paint
    If MyBitmaps.Count > 0 Then
        MyBitmaps.OrderBy(Function(item) item.Order).
            Select(Function(item)
                       e.Graphics.DrawImage(item.Image, New Rectangle(item.Position, item.Size))
                       Return item
                   End Function).ToList()
    End If
End Sub

To add a Bitmap to the List(Of BitmapObject), since you want to use an OpenFileDialog to let the user select a Bitmap, we assign this functionality to a Button and when the Bitmap is selected, a new BitmapObject is created and appended to the List.

Private Sub btnOpenFile_Click(sender As Object, e As EventArgs) Handles btnOpenFile.Click

    Dim fd As OpenFileDialog = New OpenFileDialog()
    fd.InitialDirectory = "[Images Path]"
    Dim dr As DialogResult = fd.ShowDialog()

    If dr = Windows.Forms.DialogResult.OK Then
        Dim BitmapName As String = New FileInfo(fd.FileName).Name

        Using tmpBitmap As Bitmap = New Bitmap(fd.FileName)
            MyBitmaps.Add(New BitmapObject With {
                          .Image = New Bitmap(tmpBitmap),
                          .Position = New Point(Integer.Parse(TextBox1.Text), Integer.Parse(TextBox2.Text)),
                          .Size = New Size(tmpBitmap.Height, tmpBitmap.Width),
                          .Order = MyBitmaps.Count,
                          .Name = BitmapName})

            ComboBox1.Items.Add(BitmapName)
            ComboBox1.SelectedIndex = MyBitmaps.Count - 1
            TrackBar1.Value = tmpBitmap.Height
            TrackBar2.Value = tmpBitmap.Width
            Panel1.Invalidate()
        End Using
    End If
End Sub

This is the result: (Full source code in PasteBin)