|
|
|
@@ -1,299 +0,0 @@
|
|
|
|
|
Public NotInheritable Class SystemDropShadowChrome
|
|
|
|
|
Inherits Decorator
|
|
|
|
|
|
|
|
|
|
'源码来源于:https://referencesource.microsoft.com/#PresentationFramework.Aero/parent/Shared/Microsoft/Windows/Themes/SystemDropShadowChrome.cs,6d9c27d92a8128c1
|
|
|
|
|
|
|
|
|
|
Public Shared ReadOnly ColorProperty As DependencyProperty = DependencyProperty.Register("Color", GetType(Color), GetType(SystemDropShadowChrome), New FrameworkPropertyMetadata(Color.FromArgb(&H71, &H0, &H0, &H0), FrameworkPropertyMetadataOptions.AffectsRender, New PropertyChangedCallback(AddressOf ClearBrushes)))
|
|
|
|
|
Public Property Color As Color
|
|
|
|
|
Get
|
|
|
|
|
Return CType(GetValue(ColorProperty), Color)
|
|
|
|
|
End Get
|
|
|
|
|
Set(value As Color)
|
|
|
|
|
SetValue(ColorProperty, value)
|
|
|
|
|
End Set
|
|
|
|
|
End Property
|
|
|
|
|
|
|
|
|
|
Public Shared ReadOnly CornerRadiusProperty As DependencyProperty = DependencyProperty.Register("CornerRadius", GetType(CornerRadius), GetType(SystemDropShadowChrome), New FrameworkPropertyMetadata(New CornerRadius(), FrameworkPropertyMetadataOptions.AffectsRender, New PropertyChangedCallback(AddressOf ClearBrushes)), New ValidateValueCallback(AddressOf IsCornerRadiusValid))
|
|
|
|
|
Public Property CornerRadius As CornerRadius
|
|
|
|
|
Get
|
|
|
|
|
Return CType(GetValue(CornerRadiusProperty), CornerRadius)
|
|
|
|
|
End Get
|
|
|
|
|
Set(value As CornerRadius)
|
|
|
|
|
SetValue(CornerRadiusProperty, value)
|
|
|
|
|
End Set
|
|
|
|
|
End Property
|
|
|
|
|
Private Shared Function IsCornerRadiusValid(value As Object) As Boolean
|
|
|
|
|
Dim cr As CornerRadius = CType(value, CornerRadius)
|
|
|
|
|
Return Not (cr.TopLeft < 0.0 OrElse cr.TopRight < 0.0 OrElse cr.BottomLeft < 0.0 OrElse cr.BottomRight < 0.0 OrElse Double.IsNaN(cr.TopLeft) OrElse Double.IsNaN(cr.TopRight) OrElse Double.IsNaN(cr.BottomLeft) OrElse Double.IsNaN(cr.BottomRight) OrElse Double.IsInfinity(cr.TopLeft) OrElse Double.IsInfinity(cr.TopRight) OrElse Double.IsInfinity(cr.BottomLeft) OrElse Double.IsInfinity(cr.BottomRight))
|
|
|
|
|
End Function
|
|
|
|
|
|
|
|
|
|
Private Const ShadowDepth As Double = 5
|
|
|
|
|
|
|
|
|
|
Protected Overrides Sub OnRender(drawingContext As DrawingContext)
|
|
|
|
|
Dim cornerRadius As CornerRadius = Me.CornerRadius
|
|
|
|
|
Dim shadowBounds As New Rect(New Point(ShadowDepth, ShadowDepth), New Size(RenderSize.Width, RenderSize.Height))
|
|
|
|
|
Dim color As Color = Me.Color
|
|
|
|
|
|
|
|
|
|
If shadowBounds.Width > 0 AndAlso shadowBounds.Height > 0 AndAlso color.A > 0 Then
|
|
|
|
|
Dim centerWidth As Double = shadowBounds.Right - shadowBounds.Left - 2 * ShadowDepth
|
|
|
|
|
Dim centerHeight As Double = shadowBounds.Bottom - shadowBounds.Top - 2 * ShadowDepth
|
|
|
|
|
Dim maxRadius As Double = Math.Min(centerWidth * 0.5, centerHeight * 0.5)
|
|
|
|
|
cornerRadius.TopLeft = Math.Min(cornerRadius.TopLeft, maxRadius)
|
|
|
|
|
cornerRadius.TopRight = Math.Min(cornerRadius.TopRight, maxRadius)
|
|
|
|
|
cornerRadius.BottomLeft = Math.Min(cornerRadius.BottomLeft, maxRadius)
|
|
|
|
|
cornerRadius.BottomRight = Math.Min(cornerRadius.BottomRight, maxRadius)
|
|
|
|
|
Dim brushes As Brush() = GetBrushes(color, cornerRadius)
|
|
|
|
|
Dim centerTop As Double = shadowBounds.Top + ShadowDepth
|
|
|
|
|
Dim centerLeft As Double = shadowBounds.Left + ShadowDepth
|
|
|
|
|
Dim centerRight As Double = shadowBounds.Right - ShadowDepth
|
|
|
|
|
Dim centerBottom As Double = shadowBounds.Bottom - ShadowDepth
|
|
|
|
|
Dim guidelineSetX As Double() = New Double() {centerLeft, centerLeft + cornerRadius.TopLeft, centerRight - cornerRadius.TopRight, centerLeft + cornerRadius.BottomLeft, centerRight - cornerRadius.BottomRight, centerRight}
|
|
|
|
|
Dim guidelineSetY As Double() = New Double() {centerTop, centerTop + cornerRadius.TopLeft, centerTop + cornerRadius.TopRight, centerBottom - cornerRadius.BottomLeft, centerBottom - cornerRadius.BottomRight, centerBottom}
|
|
|
|
|
drawingContext.PushGuidelineSet(New GuidelineSet(guidelineSetX, guidelineSetY))
|
|
|
|
|
cornerRadius.TopLeft += ShadowDepth
|
|
|
|
|
cornerRadius.TopRight += ShadowDepth
|
|
|
|
|
cornerRadius.BottomLeft += ShadowDepth
|
|
|
|
|
cornerRadius.BottomRight += ShadowDepth
|
|
|
|
|
Dim topLeft As New Rect(shadowBounds.Left, shadowBounds.Top, cornerRadius.TopLeft, cornerRadius.TopLeft)
|
|
|
|
|
drawingContext.DrawRectangle(brushes(Placement.TopLeft), Nothing, topLeft)
|
|
|
|
|
Dim topWidth As Double = guidelineSetX(2) - guidelineSetX(1)
|
|
|
|
|
|
|
|
|
|
If topWidth > 0 Then
|
|
|
|
|
Dim top As New Rect(guidelineSetX(1), shadowBounds.Top, topWidth, ShadowDepth)
|
|
|
|
|
drawingContext.DrawRectangle(brushes(Placement.Top), Nothing, top)
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
Dim topRight As New Rect(guidelineSetX(2), shadowBounds.Top, cornerRadius.TopRight, cornerRadius.TopRight)
|
|
|
|
|
drawingContext.DrawRectangle(brushes(Placement.TopRight), Nothing, topRight)
|
|
|
|
|
Dim leftHeight As Double = guidelineSetY(3) - guidelineSetY(1)
|
|
|
|
|
|
|
|
|
|
If leftHeight > 0 Then
|
|
|
|
|
Dim left As New Rect(shadowBounds.Left, guidelineSetY(1), ShadowDepth, leftHeight)
|
|
|
|
|
drawingContext.DrawRectangle(brushes(Placement.Left), Nothing, left)
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
Dim rightHeight As Double = guidelineSetY(4) - guidelineSetY(2)
|
|
|
|
|
|
|
|
|
|
If rightHeight > 0 Then
|
|
|
|
|
Dim right As New Rect(guidelineSetX(5), guidelineSetY(2), ShadowDepth, rightHeight)
|
|
|
|
|
drawingContext.DrawRectangle(brushes(Placement.Right), Nothing, right)
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
Dim bottomLeft As New Rect(shadowBounds.Left, guidelineSetY(3), cornerRadius.BottomLeft, cornerRadius.BottomLeft)
|
|
|
|
|
drawingContext.DrawRectangle(brushes(Placement.BottomLeft), Nothing, bottomLeft)
|
|
|
|
|
Dim bottomWidth As Double = guidelineSetX(4) - guidelineSetX(3)
|
|
|
|
|
|
|
|
|
|
If bottomWidth > 0 Then
|
|
|
|
|
Dim bottom As New Rect(guidelineSetX(3), guidelineSetY(5), bottomWidth, ShadowDepth)
|
|
|
|
|
drawingContext.DrawRectangle(brushes(Placement.Bottom), Nothing, bottom)
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
Dim bottomRight As New Rect(guidelineSetX(4), guidelineSetY(4), cornerRadius.BottomRight, cornerRadius.BottomRight)
|
|
|
|
|
drawingContext.DrawRectangle(brushes(Placement.BottomRight), Nothing, bottomRight)
|
|
|
|
|
|
|
|
|
|
If cornerRadius.TopLeft = ShadowDepth AndAlso cornerRadius.TopLeft = cornerRadius.TopRight AndAlso cornerRadius.TopLeft = cornerRadius.BottomLeft AndAlso cornerRadius.TopLeft = cornerRadius.BottomRight Then
|
|
|
|
|
Dim center As New Rect(guidelineSetX(0), guidelineSetY(0), centerWidth, centerHeight)
|
|
|
|
|
drawingContext.DrawRectangle(brushes(Placement.Center), Nothing, center)
|
|
|
|
|
Else
|
|
|
|
|
Dim figure As New PathFigure()
|
|
|
|
|
|
|
|
|
|
If cornerRadius.TopLeft > ShadowDepth Then
|
|
|
|
|
figure.StartPoint = New Point(guidelineSetX(1), guidelineSetY(0))
|
|
|
|
|
figure.Segments.Add(New LineSegment(New Point(guidelineSetX(1), guidelineSetY(1)), True))
|
|
|
|
|
figure.Segments.Add(New LineSegment(New Point(guidelineSetX(0), guidelineSetY(1)), True))
|
|
|
|
|
Else
|
|
|
|
|
figure.StartPoint = New Point(guidelineSetX(0), guidelineSetY(0))
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
If cornerRadius.BottomLeft > ShadowDepth Then
|
|
|
|
|
figure.Segments.Add(New LineSegment(New Point(guidelineSetX(0), guidelineSetY(3)), True))
|
|
|
|
|
figure.Segments.Add(New LineSegment(New Point(guidelineSetX(3), guidelineSetY(3)), True))
|
|
|
|
|
figure.Segments.Add(New LineSegment(New Point(guidelineSetX(3), guidelineSetY(5)), True))
|
|
|
|
|
Else
|
|
|
|
|
figure.Segments.Add(New LineSegment(New Point(guidelineSetX(0), guidelineSetY(5)), True))
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
If cornerRadius.BottomRight > ShadowDepth Then
|
|
|
|
|
figure.Segments.Add(New LineSegment(New Point(guidelineSetX(4), guidelineSetY(5)), True))
|
|
|
|
|
figure.Segments.Add(New LineSegment(New Point(guidelineSetX(4), guidelineSetY(4)), True))
|
|
|
|
|
figure.Segments.Add(New LineSegment(New Point(guidelineSetX(5), guidelineSetY(4)), True))
|
|
|
|
|
Else
|
|
|
|
|
figure.Segments.Add(New LineSegment(New Point(guidelineSetX(5), guidelineSetY(5)), True))
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
If cornerRadius.TopRight > ShadowDepth Then
|
|
|
|
|
figure.Segments.Add(New LineSegment(New Point(guidelineSetX(5), guidelineSetY(2)), True))
|
|
|
|
|
figure.Segments.Add(New LineSegment(New Point(guidelineSetX(2), guidelineSetY(2)), True))
|
|
|
|
|
figure.Segments.Add(New LineSegment(New Point(guidelineSetX(2), guidelineSetY(0)), True))
|
|
|
|
|
Else
|
|
|
|
|
figure.Segments.Add(New LineSegment(New Point(guidelineSetX(5), guidelineSetY(0)), True))
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
figure.IsClosed = True
|
|
|
|
|
figure.Freeze()
|
|
|
|
|
Dim geometry As New PathGeometry()
|
|
|
|
|
geometry.Figures.Add(figure)
|
|
|
|
|
geometry.Freeze()
|
|
|
|
|
drawingContext.DrawGeometry(brushes(Placement.Center), Nothing, geometry)
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
drawingContext.Pop()
|
|
|
|
|
End If
|
|
|
|
|
End Sub
|
|
|
|
|
|
|
|
|
|
Private Enum Placement
|
|
|
|
|
TopLeft = 0
|
|
|
|
|
Top = 1
|
|
|
|
|
TopRight = 2
|
|
|
|
|
Left = 3
|
|
|
|
|
Center = 4
|
|
|
|
|
Right = 5
|
|
|
|
|
BottomLeft = 6
|
|
|
|
|
Bottom = 7
|
|
|
|
|
BottomRight = 8
|
|
|
|
|
End Enum
|
|
|
|
|
Private Shared _commonBrushes As Brush()
|
|
|
|
|
Private Shared _commonCornerRadius As CornerRadius
|
|
|
|
|
Private Shared ReadOnly _resourceAccess As New Object()
|
|
|
|
|
Private _brushes As Brush()
|
|
|
|
|
|
|
|
|
|
Private Shared Sub ClearBrushes(o As DependencyObject, e As DependencyPropertyChangedEventArgs)
|
|
|
|
|
CType(o, SystemDropShadowChrome)._brushes = Nothing
|
|
|
|
|
End Sub
|
|
|
|
|
Private Shared Function CreateStops(c As Color, cornerRadius As Double) As GradientStopCollection
|
|
|
|
|
Dim gradientScale As Double = 1 / (cornerRadius + ShadowDepth)
|
|
|
|
|
Dim gsc As New GradientStopCollection From {
|
|
|
|
|
New GradientStop(c, (0.5 + cornerRadius) * gradientScale)
|
|
|
|
|
}
|
|
|
|
|
Dim stopColor As Color = c
|
|
|
|
|
stopColor.A = CByte(0.74336 * c.A)
|
|
|
|
|
gsc.Add(New GradientStop(stopColor, (1.5 + cornerRadius) * gradientScale))
|
|
|
|
|
stopColor.A = CByte(0.38053 * c.A)
|
|
|
|
|
gsc.Add(New GradientStop(stopColor, (2.5 + cornerRadius) * gradientScale))
|
|
|
|
|
stopColor.A = CByte(0.12389 * c.A)
|
|
|
|
|
gsc.Add(New GradientStop(stopColor, (3.5 + cornerRadius) * gradientScale))
|
|
|
|
|
stopColor.A = CByte(0.02654 * c.A)
|
|
|
|
|
gsc.Add(New GradientStop(stopColor, (4.5 + cornerRadius) * gradientScale))
|
|
|
|
|
stopColor.A = 0
|
|
|
|
|
gsc.Add(New GradientStop(stopColor, (5 + cornerRadius) * gradientScale))
|
|
|
|
|
gsc.Freeze()
|
|
|
|
|
Return gsc
|
|
|
|
|
End Function
|
|
|
|
|
Private Shared Function CreateBrushes(c As Color, cornerRadius As CornerRadius) As Brush()
|
|
|
|
|
Dim brushes As Brush() = New Brush(8) {}
|
|
|
|
|
brushes(Placement.Center) = New SolidColorBrush(c)
|
|
|
|
|
brushes(Placement.Center).Freeze()
|
|
|
|
|
Dim sideStops As GradientStopCollection = CreateStops(c, 0)
|
|
|
|
|
Dim top As New LinearGradientBrush(sideStops, New Point(0, 1), New Point(0, 0))
|
|
|
|
|
top.Freeze()
|
|
|
|
|
brushes(Placement.Top) = top
|
|
|
|
|
Dim left As New LinearGradientBrush(sideStops, New Point(1, 0), New Point(0, 0))
|
|
|
|
|
left.Freeze()
|
|
|
|
|
brushes(Placement.Left) = left
|
|
|
|
|
Dim right As New LinearGradientBrush(sideStops, New Point(0, 0), New Point(1, 0))
|
|
|
|
|
right.Freeze()
|
|
|
|
|
brushes(Placement.Right) = right
|
|
|
|
|
Dim bottom As New LinearGradientBrush(sideStops, New Point(0, 0), New Point(0, 1))
|
|
|
|
|
bottom.Freeze()
|
|
|
|
|
brushes(Placement.Bottom) = bottom
|
|
|
|
|
Dim topLeftStops As GradientStopCollection
|
|
|
|
|
|
|
|
|
|
If cornerRadius.TopLeft = 0 Then
|
|
|
|
|
topLeftStops = sideStops
|
|
|
|
|
Else
|
|
|
|
|
topLeftStops = CreateStops(c, cornerRadius.TopLeft)
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
Dim topLeft As New RadialGradientBrush(topLeftStops) With {
|
|
|
|
|
.RadiusX = 1,
|
|
|
|
|
.RadiusY = 1,
|
|
|
|
|
.Center = New Point(1, 1),
|
|
|
|
|
.GradientOrigin = New Point(1, 1)
|
|
|
|
|
}
|
|
|
|
|
topLeft.Freeze()
|
|
|
|
|
brushes(Placement.TopLeft) = topLeft
|
|
|
|
|
Dim topRightStops As GradientStopCollection
|
|
|
|
|
|
|
|
|
|
If cornerRadius.TopRight = 0 Then
|
|
|
|
|
topRightStops = sideStops
|
|
|
|
|
ElseIf cornerRadius.TopRight = cornerRadius.TopLeft Then
|
|
|
|
|
topRightStops = topLeftStops
|
|
|
|
|
Else
|
|
|
|
|
topRightStops = CreateStops(c, cornerRadius.TopRight)
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
Dim topRight As New RadialGradientBrush(topRightStops) With {
|
|
|
|
|
.RadiusX = 1,
|
|
|
|
|
.RadiusY = 1,
|
|
|
|
|
.Center = New Point(0, 1),
|
|
|
|
|
.GradientOrigin = New Point(0, 1)
|
|
|
|
|
}
|
|
|
|
|
topRight.Freeze()
|
|
|
|
|
brushes(Placement.TopRight) = topRight
|
|
|
|
|
Dim bottomLeftStops As GradientStopCollection
|
|
|
|
|
|
|
|
|
|
If cornerRadius.BottomLeft = 0 Then
|
|
|
|
|
bottomLeftStops = sideStops
|
|
|
|
|
ElseIf cornerRadius.BottomLeft = cornerRadius.TopLeft Then
|
|
|
|
|
bottomLeftStops = topLeftStops
|
|
|
|
|
ElseIf cornerRadius.BottomLeft = cornerRadius.TopRight Then
|
|
|
|
|
bottomLeftStops = topRightStops
|
|
|
|
|
Else
|
|
|
|
|
bottomLeftStops = CreateStops(c, cornerRadius.BottomLeft)
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
Dim bottomLeft As New RadialGradientBrush(bottomLeftStops) With {
|
|
|
|
|
.RadiusX = 1,
|
|
|
|
|
.RadiusY = 1,
|
|
|
|
|
.Center = New Point(1, 0),
|
|
|
|
|
.GradientOrigin = New Point(1, 0)
|
|
|
|
|
}
|
|
|
|
|
bottomLeft.Freeze()
|
|
|
|
|
brushes(Placement.BottomLeft) = bottomLeft
|
|
|
|
|
Dim bottomRightStops As GradientStopCollection
|
|
|
|
|
|
|
|
|
|
If cornerRadius.BottomRight = 0 Then
|
|
|
|
|
bottomRightStops = sideStops
|
|
|
|
|
ElseIf cornerRadius.BottomRight = cornerRadius.TopLeft Then
|
|
|
|
|
bottomRightStops = topLeftStops
|
|
|
|
|
ElseIf cornerRadius.BottomRight = cornerRadius.TopRight Then
|
|
|
|
|
bottomRightStops = topRightStops
|
|
|
|
|
ElseIf cornerRadius.BottomRight = cornerRadius.BottomLeft Then
|
|
|
|
|
bottomRightStops = bottomLeftStops
|
|
|
|
|
Else
|
|
|
|
|
bottomRightStops = CreateStops(c, cornerRadius.BottomRight)
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
Dim bottomRight As New RadialGradientBrush(bottomRightStops) With {
|
|
|
|
|
.RadiusX = 1,
|
|
|
|
|
.RadiusY = 1,
|
|
|
|
|
.Center = New Point(0, 0),
|
|
|
|
|
.GradientOrigin = New Point(0, 0)
|
|
|
|
|
}
|
|
|
|
|
bottomRight.Freeze()
|
|
|
|
|
brushes(Placement.BottomRight) = bottomRight
|
|
|
|
|
Return brushes
|
|
|
|
|
End Function
|
|
|
|
|
Private Function GetBrushes(c As Color, cornerRadius As CornerRadius) As Brush()
|
|
|
|
|
If _commonBrushes Is Nothing Then
|
|
|
|
|
|
|
|
|
|
SyncLock _resourceAccess
|
|
|
|
|
|
|
|
|
|
If _commonBrushes Is Nothing Then
|
|
|
|
|
_commonBrushes = CreateBrushes(c, cornerRadius)
|
|
|
|
|
_commonCornerRadius = cornerRadius
|
|
|
|
|
End If
|
|
|
|
|
End SyncLock
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
If c = CType(_commonBrushes(Placement.Center), SolidColorBrush).Color AndAlso cornerRadius = _commonCornerRadius Then
|
|
|
|
|
_brushes = Nothing
|
|
|
|
|
Return _commonBrushes
|
|
|
|
|
ElseIf _brushes Is Nothing Then
|
|
|
|
|
_brushes = CreateBrushes(c, cornerRadius)
|
|
|
|
|
End If
|
|
|
|
|
|
|
|
|
|
Return _brushes
|
|
|
|
|
End Function
|
|
|
|
|
|
|
|
|
|
End Class
|