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+行的设计器代码将使这种方式太长。
谢谢你的建议!
1条答案
按热度按时间x8diyxa71#
问题解决了。
paint方法中的代码:
会导致复发。
将其放入IF语句中:
解决了导致该问题的递归,因为如果我们指定颜色,它将立即发出递归绘制调用。
仍在清理的东西,使代码良好和无泄漏。感谢所有的优秀建议。