Transparent image over two controls with different back colors

时间:2019-01-18 19:10:22

标签: vb.net winforms transparency

I am trying to place a transparent image over two adjacent controls that have different background colors.
I want the image to remain transparent, meaning the Image needs to show the backcolor of each control.

The controls are two Panels set to different background colors and the Image (PictureBox or otherwise) is placed between the two panel controls.

Public Class frmMain 
    Private Img1 As Image = Image.FromFile("C:\xxxx.png") 

    Private Sub frmMain_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint 
        e.Graphics.DrawImage(Img1, 5, 5) 
    End Sub 
End Class

enter image description here

2 个答案:

答案 0 :(得分:2)

让我们尝试一下。

  • 在项目中创建一个新类,将其命名为 TPanel ,然后粘贴到您可以在下面找到的自定义Panel类中,覆盖现有定义。
  • 编译项​​目,然后在工具箱中找到新的TPanel控件,并将一个实例拖放到Form中。
    在窗体上,而不是在一个彩色面板中,否则它将成为另一个控件的子控件,并且将被限制在其范围之内。
  • 将事件处理程序添加到TPanel的Paint事件中,并将此代码插入处理程序方法中:

Private Sub TPanel1_Paint(sender As Object, e As PaintEventArgs) Handles TPanel1.Paint
    Dim canvas As Control = DirectCast(sender, Control)
    Dim rect As Rectangle = ScaleImageFrame(imgBasketBall, canvas.ClientRectangle)

    e.Graphics.SmoothingMode = SmoothingMode.AntiAlias
    e.Graphics.CompositingMode = CompositingMode.SourceOver
    e.Graphics.PixelOffsetMode = PixelOffsetMode.Half
    e.Graphics.DrawImage(imgBasketBall, rect)
End Sub

Private Function ScaleImageFrame(sourceImage As Bitmap, destinationFrame As Rectangle) As Rectangle
    Dim rect As RectangleF = New RectangleF(0, 0, sourceImage.Width, sourceImage.Height)
    'Define the ratio between the Image Rectangle and the Container ClientRectangle
    Dim ratio As Single = CType(Math.Max(destinationFrame.Width, destinationFrame.Height) /
                                Math.Max(rect.Width, rect.Height), Single)
    rect.Size = New SizeF(rect.Width * ratio, rect.Height * ratio)
    'Use Integer division to avoid negative values
    rect.Location = New Point((destinationFrame.Width - CInt(rect.Width)) \ 2,
                              (destinationFrame.Height - CInt(rect.Height)) \ 2)
    Return Rectangle.Round(rect)
End Function
  • 在窗体中,创建将包含图像的位图对象的实例;还可以设置面板的位置( TPanel
    名为 panColored1 panColored2 的控件应该是必须放置图像的两个现有面板的名称。示例代码使用TPanel1.Location( (...) )
  • 将Image放置在2个面板的中间

Private imgBasketBall As Bitmap = Nothing

Public Sub New()
    InitializeComponent()
    imgBasketBall = DirectCast(Image.FromFile("basketball.png").Clone(), Bitmap)
    TPanel1.Size = New Size(120, 120)
    TPanel1.Location = New Point(panColored1.Left + (panColored1.Width - TPanel1.Width) \ 2,
                                 panColored1.Top + (panColored1.Height + panColored2.Height - TPanel1.Height) \ 2)
    TPanel1.BringToFront()
End Sub

结果:

Transparent Panel Scaled Image

      Bitmap Size           Bitmap Size 
      (1245x1242)           (1178x2000)

TPanel (透明面板)类:

Imports System.ComponentModel

<DesignerCategory("Code")>
Public Class TPanel
    Inherits Panel
    Private Const WS_EX_TRANSPARENT As Integer = &H20
    Public Sub New()
        Me.SetStyle(ControlStyles.AllPaintingInWmPaint Or
                    ControlStyles.UserPaint Or
                    ControlStyles.Opaque Or
                    ControlStyles.ResizeRedraw, True)
        Me.SetStyle(ControlStyles.OptimizedDoubleBuffer, False)
        Me.UpdateStyles()
    End Sub

    Protected Overrides Sub OnPaint(e As PaintEventArgs)
        e.Graphics.FillRectangle(Brushes.Transparent, Me.ClientRectangle)
        MyBase.OnPaint(e)
    End Sub

    Protected Overrides ReadOnly Property CreateParams() As CreateParams
        Get
            Dim parameters As CreateParams = MyBase.CreateParams
            parameters.ExStyle = parameters.ExStyle Or WS_EX_TRANSPARENT
            Return parameters
        End Get
    End Property
End Class

答案 1 :(得分:0)

还有一些您也可以尝试的方法,它虽然不专业,但是可以工作。将图像分成两半。在其中一个面板上绘制前半部分,在另一个面板上绘制后半部分。 确保将System.IO导入项目中。

用于拆分的代码如下:

Imports System.IO
...
Public Function SplitImage(ByVal imgpath As String) As Image()
    Dim img As Image = Image.FromFile(imgpath)
    Dim bmp As Bitmap = DirectCast(img, Bitmap)
    Dim i As Integer = bmp.Height / 2
    Dim image1 As Bitmap = New Bitmap(bmp.Width, i)
    Dim image2 As Bitmap = New Bitmap(bmp.Width, i)
    Dim yPos As Integer = 0
    For x As Integer = 0 To image1.Width - 1
        For y As Integer = 0 To image1.Height - 1
            image1.SetPixel(x, y, bmp.GetPixel(x, y))
            yPos = y
        Next
    Next
    yPos += 1
    Dim ycount As Integer = 0
    For x As Integer = 0 To image2.Width - 1
        For y As Integer = yPos To bmp.Height - 1
            If ycount = i Then
                ycount -= 1
            End If
            image2.SetPixel(x, ycount, bmp.GetPixel(x, y))
            ycount += 1
        Next
        ycount = 0
    Next
    Dim ms As MemoryStream = New MemoryStream
    Dim ms1 As MemoryStream = New MemoryStream
    image1.Save(ms, Imaging.ImageFormat.Png)
    image2.Save(ms1, Imaging.ImageFormat.Png)
    Dim returnedImage(2) As Image
    returnedImage(0) = image1
    returnedImage(1) = image2
    Return returnedImage
End Function

在窗体上创建两个面板(Panel1和Panel2)和一个Button(Button1)。 将两个面板放置在所需的位置,将面板的BackgroundImageLayout属性设置为StretchImage。 然后从您的代码中可以像这样调用函数,即从Button的click事件:

Public Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim pic() As Image = SplitImage("C:\xxxx.png")
    Panel1.BackgroundImage = pic(0)
    Panel2.BackgroundImage = pic(1)
End Sub

有关Bitmap类的更多信息,请查看此链接Bitmap Class