具有不同背景颜色的两个控件上的透明图像
Transparent image over two controls with different back colors
我正在尝试将透明图像放置在两个具有不同背景颜色的相邻控件上。
我希望图像保持透明,这意味着图像需要显示每个控件的背景色。
控件是设置为不同背景颜色的两个面板,图像(PictureBox 或其他)放置在两个面板控件之间。
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
让我们试试这个。
- 在项目中新建一个class,命名为
TPanel
并粘贴到自定义面板class中,您可以在下面找到,覆盖现有定义。
- 编译项目然后在工具箱中找到新的
TPanel
控件并将一个实例放入窗体中。
在窗体上,而不是在其中一个彩色面板内,否则它将成为另一个控件的子控件,并且将被限制在其边界内。
- 向
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( (...) )
将图像定位在 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
结果:
Bitmap Size Bitmap Size
(1245x1242) (1178x2000)
TPanel
(透明面板)class:
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
还有一些你也可以试试,可能不专业但是很管用。将图像分成两半。在一个面板上绘制上半部分,在另一个面板上绘制下半部分。
请务必在您的项目中导入 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)和一个按钮 (Button1)。
将两个面板按照您想要的方式放置,将面板的 BackgroundImageLayout
属性 设置为 StretchImage
。
然后从你的代码中你可以像这样调用函数,即从按钮的点击事件:
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
Class 的更多信息,请查看此 link Bitmap Class
我正在尝试将透明图像放置在两个具有不同背景颜色的相邻控件上。
我希望图像保持透明,这意味着图像需要显示每个控件的背景色。
控件是设置为不同背景颜色的两个面板,图像(PictureBox 或其他)放置在两个面板控件之间。
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
让我们试试这个。
- 在项目中新建一个class,命名为
TPanel
并粘贴到自定义面板class中,您可以在下面找到,覆盖现有定义。 - 编译项目然后在工具箱中找到新的
TPanel
控件并将一个实例放入窗体中。
在窗体上,而不是在其中一个彩色面板内,否则它将成为另一个控件的子控件,并且将被限制在其边界内。 - 向
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( (...) )
将图像定位在 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
结果:
Bitmap Size Bitmap Size
(1245x1242) (1178x2000)
TPanel
(透明面板)class:
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
还有一些你也可以试试,可能不专业但是很管用。将图像分成两半。在一个面板上绘制上半部分,在另一个面板上绘制下半部分。
请务必在您的项目中导入 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)和一个按钮 (Button1)。
将两个面板按照您想要的方式放置,将面板的 BackgroundImageLayout
属性 设置为 StretchImage
。
然后从你的代码中你可以像这样调用函数,即从按钮的点击事件:
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
Class 的更多信息,请查看此 link Bitmap Class