【问题标题】:Unable To Make Front Control Transparent Over PictureBox无法使 PictureBox 上的前端控件透明
【发布时间】:2014-11-20 23:01:48
【问题描述】:

我正在尝试在 PictureBox 控件的顶部放置一个自定义用户控件,但我终其一生都不知道如何设置用户控件的透明度,这样它就不会切掉 PictureBox 图像。

我的用户控件由中间带有文本的 RectangleShape 组成,用于在图像顶部创建一个“徽章”图标(见下图)。 PictureBox 和 User Control 都位于 Panel 控件中,我设置了 PictureBox.SendToBack() 属性和 UserControl.BringToFront() 属性。

我剩下的是:

我的代码如下所示:

Option Explicit On
Option Strict On

Imports Microsoft.VisualBasic.PowerPacks

Public Class BadgeIcon
    Inherits UserControl

    Private _value As Integer
    Private canvas As New ShapeContainer
    Private Badge_Icon As New RectangleShape
    Private rect As New Rectangle
    Private m_BorderColor As Color = Color.White
    Private m_FillColor As Color = Color.Red
    Private m_BorderThickness As Integer = 2
    Private m_BadgeFont As New Font("Segoe UI", 7, FontStyle.Bold)
    Private m_BadgeText As String
    Private m_TextColor As New SolidBrush(Color.White)
    Private m_TextSize As Size
    Private m_TextPadding As Integer = 5

    Public Property Value() As Integer
        Get
            Return _value
        End Get
        Set(value As Integer)
            _value = value
            m_BadgeText = CStr(_value)
            m_TextSize = TextRenderer.MeasureText(m_BadgeText, m_BadgeFont)
            rect.Width = m_TextSize.Width + m_TextPadding
            rect.Height = m_TextSize.Height + m_TextPadding
            Me.Refresh()
        End Set
    End Property

    Protected Overrides ReadOnly Property CreateParams() As System.Windows.Forms.CreateParams
        Get
            Dim cp As CreateParams = MyBase.CreateParams
            cp.ExStyle = &H20
            Return cp
        End Get
    End Property


    Sub New()
        ' This call is required by the designer.
        InitializeComponent()
        SetStyle(ControlStyles.SupportsTransparentBackColor, True)
        SetStyle(ControlStyles.Opaque, False)
        SetStyle(ControlStyles.DoubleBuffer, True)
        SetStyle(ControlStyles.AllPaintingInWmPaint, True)
        SetStyle(ControlStyles.UserPaint, True)
        Me.BackColor = Color.FromArgb(0, 0, 0, 0)
        UpdateStyles()

        ' Add any initialization after the InitializeComponent() call.
        canvas.Parent = Me
        Badge_Icon.Parent = canvas
        canvas.BackColor = Color.FromArgb(0, 0, 0, 0)

        'Create Badge Icon
        With Badge_Icon
            .BackColor = Color.FromArgb(0, 0, 0, 0)
            .BorderColor = m_BorderColor
            .BorderWidth = m_BorderThickness
            .BorderStyle = Drawing2D.DashStyle.Solid
            .CornerRadius = 11
            .FillColor = m_FillColor
            .FillStyle = FillStyle.Solid
            .SelectionColor = Color.Transparent
        End With

        AddHandler Badge_Icon.Paint, AddressOf BadgeIcon_Paint
    End Sub

    Protected Overrides Sub OnPaint(e As PaintEventArgs)
        MyBase.OnPaint(e)
        DrawBadgeIcon(e)
    End Sub

    Public Sub DrawBadgeIcon(e As PaintEventArgs)
        Try
            'Alter the size of the icon to fix the text
            With Badge_Icon
                .Location = New Point(rect.Left + 1, rect.Top + 1)
                .Size = New Size(rect.Width, rect.Height - 1)
            End With

        Catch ex As Exception
            ErrorTrap(ex, "cls_NotificationBadgeIcon: DrawBadgeIcon()")
        End Try
    End Sub

    Private Sub BadgeIcon_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs)
        Dim textRect As New Rectangle(2, 2, m_TextSize.Width + m_TextPadding - 1, m_TextSize.Height + m_TextPadding - 2)

        'Draw the Text
        Dim flags As New StringFormat
        flags.Alignment = StringAlignment.Center
        flags.LineAlignment = StringAlignment.Center
        e.Graphics.TextRenderingHint = Drawing.Text.TextRenderingHint.ClearTypeGridFit
        e.Graphics.DrawString(m_BadgeText, m_BadgeFont, m_TextColor, textRect, flags)
    End Sub

End Class

然后将所有内容添加到我的主表单中,我调用以下内容:

Dim pic As New PictureBox
        pic.Image = My.Resources.Notifications
        pic.SizeMode = PictureBoxSizeMode.StretchImage
        pic.Location = New Point(21, 221)
        pic.Size = New Size(42, 29)
        pnlLeftMenuBar.Controls.Add(pic)
        pic.SendToBack()

Dim Counter_Notify As New BadgeIcon
Counter_Notify.Location = New Point(50, 240)
        pnlLeftMenuBar.Controls.Add(Counter_Notify)
        Counter_Notify.BringToFront()

并且只需使用Counter_Notify.Value = 1 来更新计数器值。

如何删除切掉背景图像的方形矩形?还是我应该以完全不同的方式进行设置?我对用户控件有点陌生。

任何帮助表示赞赏。谢谢

【问题讨论】:

  • 透明背景并不代表你认为的那样。对于透明背景,Net/Windows 使用父背景色。由于您的 UC 的父级是面板,这就是要绘制的内容。当您在带有不同内容的表单上拖动标签时,您可以看到它发生了变化。您可以将徽章/叠加层绘制到要修改的图像上,而不是堆叠控件。
  • @Plutonix 好吧...我确实将图像直接绘制到面板中,这确实给了我所需的结果,但是,我无法将任何事件处理程序附加到图像(例如工具提示和点击事件),所以我选择了一个图片框。那么这个问题还有什么办法吗?
  • 在图像上绘制叠加层,将图像发布到面板或 picbox 并使用控件的事件进行点击
  • @Plutonix 那么您是不是建议根本不使用用户控件?只需创建一个 PictureBox 控件,添加图像,然后在顶部绘制 RectangleShape?
  • 成功了,你看到了面板的背景。因为您已将其添加到面板中,所以将其添加到 pic 中。也不需要特殊代码,只需将 BackColor 设置为 Color.Transparent。是的,只是在 pic.Paint 事件的事件处理程序中绘制它会更有效。

标签: vb.net user-controls transparency picturebox


【解决方案1】:

使用绘画事件,您可以直接在图片框本身上进行绘制。

Private Sub pb__Paint(sender As System.Object, e As System.Windows.Forms.PaintEventArgs) Handles pb.Paint
 Dim bgRect As New Rectangle({x,y,width,height})
 Dim textRect As New Rectangle(bgRect.X - {?}, bgRect.Y = {?}, width, height)
 e.Graphics.FillEllipse(New SolidBrush(Color.Red), bgRect)
 e.Graphics.DrawEllipse(New Pen(Color.White, 10), bgRect)
 Using sf As New StringFormat
  sf.LineAlignment = StringAlignment.Center
  sf.Alignment = StringAlignment.Center
 e.Graphics.DrawString("1", {your font}, {your brush}, textRect, sf)
 End Using
End Sub

【讨论】:

  • 只是通过你的例子,看起来这可以很好地工作。无论如何我可以将椭圆更改为圆角矩形,尽管徽章中放入的文本越多,它开始看起来越像椭圆(这是我试图避免的)?
  • 椭圆的形状取决于高度和宽度,如果它们相等,它将是圆形而不是椭圆形
  • 抱歉,我确实理解,但是,我只希望椭圆以宽度方式增长,而不是高度。我已经根据文本的宽度调整了您的示例以增加椭圆的宽度,但是一旦达到 3 位数,我就会得到一个椭圆形。
  • 您可以制作第二个矩形以使文本增长,而不是 Ellipse 和 Stringformat 应用于该矩形
  • 感谢大家的帮助和帮助。我现在拥有我想要实现的目标!
猜你喜欢
  • 2022-01-17
  • 2017-11-28
  • 1970-01-01
  • 2019-07-27
相关资源
最近更新 更多