Winforms .net 4.7.2简单自定义控件挂起VS 2019设计器

nlejzf6q  于 2023-03-24  发布在  .NET
关注(0)|答案(1)|浏览(101)

vb.net 4.7.2 Winforms,VS 2019 Pro最新补丁。
我使用在这里找到的代码(Vertical Tab Control with horizontal text in Winforms)创建了Winforms Tab Control的子类,并对其进行了调整(以清理内存泄漏)。虽然它在设计器中为空时按预期工作,但在几个选项卡上创建一些嵌套的TableLayoutPanels并使用dock fill填充控件,导致VS 2019无休止地等待。
我已经通过尝试添加一个标志来防止它递归,从而将它隔离到绘制事件处理程序中;这解决了挂起,但没有什么会吸引设计师。所以,为了回答评论中的一个问题,看起来paint可能会被反复调用。但我在paint方法中没有看到任何冒犯,这将花费很长时间,也没有任何会递归的东西。
该控件的代码如下。有什么想法吗?

Option Strict On
Option Explicit On

Imports System.Drawing.Drawing2D

''' <summary>
''' Tab Control with "tabs" vertically stacked on the left.
''' </summary>
Public Class DotNetBarTabControl
Inherits System.Windows.Forms.TabControl

''' <summary>
''' Is there a border?  True if yea.
''' </summary>
Private _bBorder As Boolean = False

''' <summary>
''' Control property that shows true if there is a border.
''' </summary>
''' <returns></returns>
Public Property Border As Boolean
    Get
        Return _bBorder
    End Get
    Set(value As Boolean)
        _bBorder = value
    End Set
End Property

''' <summary>
''' Constructor.
''' </summary>
Sub New()
    SetStyle(ControlStyles.AllPaintingInWmPaint Or ControlStyles.ResizeRedraw Or ControlStyles.UserPaint Or ControlStyles.DoubleBuffer, True)
    DoubleBuffered = True
    SizeMode = TabSizeMode.Fixed
    ItemSize = New Size(44, 136)
End Sub

''' <summary>
''' Override of the CreateHandle Event Handler.
''' </summary>
Protected Overrides Sub CreateHandle()
    MyBase.CreateHandle()
    Alignment = TabAlignment.Left
End Sub

''' <summary>
''' Override of the paint routine, to paint the control.
''' </summary>
''' <param name="e">Painting Event Arguments.</param>
''' <remarks>
''' 2023-03-10 JFT: Add invocation of mybase.paint to remedy hang issue in designer.
''' 2023-03-07 JFT: Implement USING statements to remedy significant memory leaks in the 
'''                 original StackOverflow-obtained code.  Tests showed that memory leaks
'''                 were reduced to zero.
''' </remarks>
Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)
    MyBase.OnPaint(e)
    Using B As New Bitmap(Width, Height)
        Using G As Graphics = Graphics.FromImage(B)
            Try : SelectedTab.BackColor = Color.White : Catch : End Try
            G.Clear(Color.White)
            Using SB As New SolidBrush(Color.FromArgb(246, 248, 252))
                G.FillRectangle(SB, New Rectangle(0, 0, ItemSize.Height + 4, Height))
                Using P_170_187_204 As New Pen(Color.FromArgb(170, 187, 204))
                    If _bBorder Then
                        G.DrawLine(P_170_187_204, New Point(Width - 1, 0), New Point(Width - 1, Height - 1))    'comment out to get rid of the borders
                        G.DrawLine(P_170_187_204, New Point(ItemSize.Height + 1, 0), New Point(Width - 1, 0))                   'comment out to get rid of the borders
                        G.DrawLine(P_170_187_204, New Point(ItemSize.Height + 3, Height - 1), New Point(Width - 1, Height - 1)) 'comment out to get rid of the borders
                    End If
                    G.DrawLine(P_170_187_204, New Point(ItemSize.Height + 3, 0), New Point(ItemSize.Height + 3, 999))
                    For i As Integer = 0 To TabCount - 1
                        If i = SelectedIndex Then
                            Dim x2 As Rectangle = New Rectangle(New Point(GetTabRect(i).Location.X - 2, GetTabRect(i).Location.Y - 2), New Size(GetTabRect(i).Width + 3, GetTabRect(i).Height - 1))
                            Dim myBlend As New ColorBlend()
                            myBlend.Colors = {Color.FromArgb(232, 232, 240), Color.FromArgb(232, 232, 240), Color.FromArgb(232, 232, 240)}
                            myBlend.Positions = {0.0F, 0.5F, 1.0F}
                            Using lgBrush As New LinearGradientBrush(x2, Color.Black, Color.Black, 90.0F)
                                lgBrush.InterpolationColors = myBlend
                                G.FillRectangle(lgBrush, x2)
                            End Using '  lgBrush As New LinearGradientBrush(x2, Color.Black, Color.Black, 90.0F)
                            G.DrawRectangle(P_170_187_204, x2)
                            G.SmoothingMode = SmoothingMode.HighQuality
                            Dim p() As Point = {New Point(ItemSize.Height - 3, GetTabRect(i).Location.Y + 20), New Point(ItemSize.Height + 4, GetTabRect(i).Location.Y + 14), New Point(ItemSize.Height + 4, GetTabRect(i).Location.Y + 27)}
                            G.FillPolygon(Brushes.White, p)
                            G.DrawPolygon(P_170_187_204, p)
                            Using fBold As New Font(Font.FontFamily, Font.Size, FontStyle.Bold)
                                Using sfCenterCenter As New StringFormat With {.LineAlignment = StringAlignment.Center, .Alignment = StringAlignment.Center}
                                    If ImageList IsNot Nothing Then
                                        Try
                                            If ImageList.Images(TabPages(i).ImageIndex) IsNot Nothing Then
                                                G.DrawImage(ImageList.Images(TabPages(i).ImageIndex), New Point(x2.Location.X + 8, x2.Location.Y + 6))
                                                G.DrawString("      " & TabPages(i).Text, Font, Brushes.DimGray, x2, sfCenterCenter)
                                                G.DrawString(TabPages(i).Text, fBold, Brushes.DimGray, x2, sfCenterCenter)
                                            Else
                                                G.DrawString(TabPages(i).Text, fBold, Brushes.DimGray, x2, sfCenterCenter)
                                            End If
                                        Catch ex As Exception
                                            G.DrawString(TabPages(i).Text, fBold, Brushes.DimGray, x2, sfCenterCenter)
                                        End Try
                                    Else
                                        G.DrawString(TabPages(i).Text, fBold, Brushes.DimGray, x2, sfCenterCenter)
                                    End If
                                End Using ' sfCenterCenter As New StringFormat 
                            End Using ' fBold As New Font(Font.FontFamily, Font.Size, FontStyle.Bold)
                            Using P_200_200_250 As New Pen(Color.FromArgb(200, 200, 250))
                                G.DrawLine(P_200_200_250, New Point(x2.Location.X - 1, x2.Location.Y - 1), New Point(x2.Location.X, x2.Location.Y))
                                G.DrawLine(P_200_200_250, New Point(x2.Location.X - 1, x2.Bottom - 1), New Point(x2.Location.X, x2.Bottom))
                            End Using ' P_200_200_250 As New Pen(Color.FromArgb(200, 200, 250))
                        Else
                            Dim x2 As Rectangle = New Rectangle(New Point(GetTabRect(i).Location.X - 2, GetTabRect(i).Location.Y - 2), New Size(GetTabRect(i).Width + 3, GetTabRect(i).Height + 1))
                            G.FillRectangle(SB, x2)
                            G.DrawLine(P_170_187_204, New Point(x2.Right, x2.Top), New Point(x2.Right, x2.Bottom))
                            If ImageList IsNot Nothing Then
                                Try
                                    If ImageList.Images(TabPages(i).ImageIndex) IsNot Nothing Then
                                        G.DrawImage(ImageList.Images(TabPages(i).ImageIndex), New Point(x2.Location.X + 8, x2.Location.Y + 6))
                                        G.DrawString("      " & TabPages(i).Text, Font, Brushes.DimGray, x2, New StringFormat With {.LineAlignment = StringAlignment.Center, .Alignment = StringAlignment.Center})
                                    Else
                                        G.DrawString(TabPages(i).Text, Font, Brushes.DimGray, x2, New StringFormat With {.LineAlignment = StringAlignment.Center, .Alignment = StringAlignment.Center})
                                    End If
                                Catch ex As Exception
                                    G.DrawString(TabPages(i).Text, Font, Brushes.DimGray, x2, New StringFormat With {.LineAlignment = StringAlignment.Center, .Alignment = StringAlignment.Center})
                                End Try
                            Else
                                G.DrawString(TabPages(i).Text, Font, Brushes.DimGray, x2, New StringFormat With {.LineAlignment = StringAlignment.Center, .Alignment = StringAlignment.Center})
                            End If
                        End If
                    Next
                End Using ' P_170_187_204 As New Pen(Color.FromArgb(170, 187, 204))
                e.Graphics.DrawImage(CType(B.Clone, Bitmap), 0, 0)
            End Using ' SB as new SolidBrush
        End Using ' Graphics.FromImage(B)
    End Using ' B as new bitmap
    GC.Collect() ' clean up memory freed from Using blocks
End Sub

End Class

我会添加代码的设计器的窗口使用的控制,但我认为,增加1000+行的设计器代码将使这种方式太长。
谢谢你的建议!

x8diyxa7

x8diyxa71#

问题解决了。
paint方法中的代码:

Try : SelectedTab.BackColor = Color.White : Catch : End Try

会导致复发。
将其放入IF语句中:

if SelectedTab.BackColor <> Color.White then
        Try : SelectedTab.BackColor = Color.White : Catch : End Try
    End If

解决了导致该问题的递归,因为如果我们指定颜色,它将立即发出递归绘制调用。
仍在清理的东西,使代码良好和无泄漏。感谢所有的优秀建议。

相关问题